Android设备碎片化问题一直被开发者广为诟病,而且,因为目前手机屏幕越来越来,分辨率越来越高,大有愈演愈烈的趋势。除了等待Google给出一个更加有效的解决方案以外,我们只能尽量适应当前的环境,尽量让自己的产品能够在更多的产品上正常运行。
在Google的建议下,开发者普遍使用dpi/dp单位,进行UI设计。本文将会介绍dalvik基于dpi加载资源的规则。
DPI
DPI,全称 dots per inch,意为每英寸的直线上像素点的数量。dpi越高,屏幕的画面越清晰,画质越细腻。
目前的Android设备支持以下几种DPI:
类别 | dpi | 缩放比率 | 代表机型 |
---|---|---|---|
LDPI | 120 | 75% | 已经被市场淘汰 |
MDPI | 160 | 100% | 基本被市场淘汰 |
TVDPI | 213 | 133% | Google Nexus 7 |
HDPI | 240 | 150% | Sumsong Glaxy S2, Google Nexus S, MOTO Droid |
XHDPI | 320 | 200% | Sumsong Glaxy S3, Sumsong Note2, Google Nexus 4 |
XXHDPI | 480 | 300% | 目前市场上各品牌的旗舰机:Sumsong Glaxy S4、 Asus Padfone Infinite、HTC One、 小米3 |
上面表格中dpi又称归一化DPI,可以算是一种“理想化”的DPI标准。
以Eclipse新建Android项目默认提供的机器人ICON为例:
在drwable-hdpi的文件夹中,ic_launcher.png的size为72*72,而drawable-xhdpi文件夹中的ic_launcher.png的size为96*96。
理论上来说,在Sumsong Note2(5.5寸,1280*700,XHDPI)上,会加载drawable-xhdpi中的ic_launcher.png,96/320=0.3,使用者会看到一个0.3*0.3英寸的机器人ICON,而在Sumsong的Glaxy S2上(4.3寸,480*800,HDPI)上,会加载drawable-hdpi中到ic_launcher.png,72/240=0.3,使用者仍旧会看到一个0.3*0.3英寸的机器人ICON。所以,从结果上来说,使用者在不同的设备上得到了相同到UI效果,而且,因为在Note2上使用了96*96的ICON, 可以获得更加精细的画面,这似乎是个很理想到结果:即维持了体验的一致性,又最大化的利用了屏幕的显示效果。
但是,理论和实际总是会有些微妙的差别。设备制造厂商为了迎合消费者的喜好,会生产各种屏幕尺寸的设备,而Android的归一化DPI只有6种(其中2种还是被市场淘汰的),最终呈现给开发者的结果就是,硬件设备的物理dpi(或者说ppi,pixel per inch)总是或大或小,和归一化dpi有一定差距,厂商会根据自己的需要设定设备的归一化DPI,而dalvik进而根据这个归一化DPI来加载资源,绘制界面。
Note2的物理分辨率其实是267ppi(其实,更接近HDPI,而非XHDPI),而非dalvik认为的320,96/267=0.36,所以,使用者实际看到的是一个0.36*0.36的ICON,而S2的物理分辨率是219,72/219=0.33,所以使用者实际看到的ICON为0.33*0.33寸。所以,界面的实际效果会和开发者的预想有一定偏差。
幸运的是,只要设备制造商设定的归一化DPI和设备的物理分辨率差距不会大的离谱(想象一下,DPI设置不佳导致大部分app都无法正常运行的设备,能够大卖么?),界面的最终效果还是能够达到开发者的要求的。
基于DPI的资源加载优先级
首先,我们需要明白dalvik匹配最佳资源的策略,从Google的官方资料,我们可以知道dalvik是这样工作的: