Android图片适配问题分析

来源:互联网 发布:外包淘宝客服招聘 编辑:程序博客网 时间:2024/06/06 00:59

一些重要概念

       首先来看一些Android屏幕适配相关的基本概念:

屏幕尺寸:单位为英寸(inch),也就是我们常说的手机屏幕是多少寸。这个尺寸指的是屏幕对角线的长度。

分辨率:屏幕高和宽的像素数, 现在常见的分辨率有640*480、1280*720、1920*1080。

px:像素,显示屏上的一个光点就是一个像素。

dp(dip):设备无关像素,Android上特有的一种度量单位。相同dp尺寸的图片在不同显示屏上看起来的大小是一样的。

sp: scaled pixels(可缩放像素),类似于dp,所不同的是大小会随着系统字体的调整而调整,适合于设置字体大小。

ppi: pixel per inch,每英寸的像素数,即屏幕密度。这个值是设备自己决定的,是写死的。同样尺寸的图片,手机的ppi越大,在屏幕上显示出来就会越小。

       那么ppi这个值是怎么来的呢?首先要明确的是这个值并不是屏幕横向分辨率除以屏幕横向尺寸。

       如果屏幕横向分辨率为w,纵向分辨率为h,屏幕尺寸为s,那么ppi、w、h和s符合下面的公式:

    (ppi*s)^2 = w^2 + h^2

       从而得到dpi的计算公式

    ppi=(√(w^2 + h^2))/ s)

       查询华为荣耀6的相关参数,分辨率为1920*1080,ppi为403,屏幕大小为5.5英寸,将相应的参数套入上面的公式,刚好是相等的。


ppi和drawable目录的对应关系

       Android的res目录下一般会存在如下几个图片资源目录,drawable、drawable-ldpi、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi。系统根据当前手机的ppi去匹配相应的目录寻找对应的资源。mdpi的屏幕密度是160,他是标准的参考密度。所以计算比例的时候它的比例值是1,其他屏幕密度的参考比例都是以这个为依据。资源目录和ppi的对应情况如下图。也就是说,假如当前手机的ppi为230,首先会从hdpi目录中寻找图片,如果当前手机ppi为430,首先会从xxhdpi目录中寻找图片。



Android图片选择策略

       如果系统没有在当前当前ppi对应的目录下找到需要的资源,就会依据一个策略去其他目录去寻找图片,这个策略是固定的,具体寻找图片的策略如下:

1、去ppi对应的目录去找,如果找到就拿来用。

2、如果没找到,就去比这个密度高一级的目录里面去找,如果找到就拿来用。

3、如果没找到就继续往上找。以此类推。

4、如果到了xxhdpi目录还没有找到的话,就会去比自身屏幕密度低一级的目录去找,如果低一级的目录>=hdpi,找到了就拿来用。

5、如果没找到, 就去mdpi目录去找, 如果找到了,就拿来用。

6、如果没找到,就去默认的drawble目录里去找, 如果找到了就拿来用。

7 、如果没找到,再去最低的ldpi目录里去找。如果找到了,就拿来用。

8、如果没找到, 那就是没找到了, 图片无法显示。


Android系统对图片的缩放规则

       上面提到,如果在手机ppi对应的目录中没有找到图片,就会按照一定的策略去其他目录找,找到之后会怎么处理呢?

       对于放在不同目录下的图片, 系统会按照一定比例对原始的图片进行放大或者缩小, 具体的放大缩小比例可参考下表, 图片所在目录和对应的屏幕密度相同时图片缩放比例为1,而横向的比例表示分别放在该密度手机上运行时图片被缩放的比例。

       对原始图片的缩放倍数。



实验验证

       下面我们来验证图片选择策略及缩放问题

       首先找到一张图片,图片尺寸为480*720,decode之后占用的大小应该为480*720*4 = 1.38M(这里默认decode成ARGB_8888格式,所以一个像素占4个字节)。我的测试手机为480ppi,默认会去加载xxhdpi中的图片。

       首先在不加载图片的情况下,观察App启动后占用的内存大小为17.99M。


       如果图片放在xxhdpi目录,从Android Monitor中观察到的内存大小为19.31M。这种情况下,图片是不会被缩放的,依据上面的描述,图片原始大小为1.38M,那么App占用的内存大小就应该为17.99M + 1.38M = 19.37M,排除Android Monitor测试误差的影响,这与我们从Android Monitor中观察到的结果是基本一致的。

       如果图片放在hdpi目录,从Android Monitor中观察到的内存大小为23.27M。这种情况下,图片在decode过程中会被缩放,根据之前讨论的缩放规则,图片的宽高都会被放大为原来的2倍,即大小会被放大为原来的4倍。图片原始大小为1.38M,缩放后的大小为1.38M * 4 = 5.52M,那么App占用的内存大小就应该为17.99M + 5.52M = 23.51M,这个值与观察值23.27M也是基本一致的。

       这样就验证了我们上面提到的Android系统对图片的选择和缩放策略。

       同时,我们也注意到一个问题,如果将图片放在很低ppi对应的目录(如mdpi),而App安装在高ppi的手机上(如ppi为480),则图片加载后占用的内存将会很大,倘若图片本身的尺寸又很大,就很容易出现OOM的问题。这是我们在开发中需要留意的。


屏幕适配的原则

       最好的情况当然是每个drawable目录都对应的放一张切图,这就不存在图片缩放问题了。但是对于对包体积敏感的产品,肯定是无法接受大量重复的切图的,这会导致apk变得很大。如果只放置一套图片,会有什么问题呢?一个是系统对图片进行缩放本身就是会损失应用性能的,尤其是显示大量图片的时候。另一个问题就是系统对图片进行放大会变模糊,缩小图片又可能会导致图片出现失真。

       为了尽可能的避免上面这些情况,最好的实践是在当前主流的ppi对应的资源目录中放置一到两套资源,然后其他的目录采用系统自动缩放的方式。

参考文档:http://blog.csdn.net/xiebudong/article/details/37040263/

3 0