简短不割,直入正文。iOS最鄙视Android的是什么?乔布斯每场发布会必鄙视Android的是什么?UI!!为什么iOS总是有那么多美轮美奂的界面,而Android却总显的那么苍白无力?主要原因就是Android手机TM屏幕尺寸太多了,各种屏幕尺寸配上各种分辨率,让一大帮程序员对做界面没了兴趣,再加上iOS与生俱来的出色的图形动画性能和乔布斯教主般的吸血光环,又让一大帮程序员做起了iOS。Google当然意识到了这个问题,在新版本中不断的提升图形性能,发布Android UI规范,在Android 4.0以后加强控制硬件规格,这都为做出漂亮的界面打下了基础,但论使用度和程序员接触最深的,当属一整套的屏幕适配方案。
打做Android UI的第一天起,所有的学习资料都在告诉你,控件定位要用dp,不能用px,但是,这TM是为什么?于是,所有的学习资料又都在告诉你,Android中屏幕被分为了高、中、低等密度以及大、中、小等尺寸,做界面不用考虑分辨率,只需考虑密度,但是,这TM又是为了什么?然后,所有的学习资料就都不说话了。于是,我只能从它们谈论的只言片语中找出历史的正文。
声明:以下信息有部分内容纯属猜测。
早在公元2008年,第一款Android手机横空出世,这就是由HTC出品,T-Mobile定制的T-Mobile G1,搭载3.17英寸,320*480(HVGA)分辨率的显示屏,此时的Android还是1.0版本。既然是第一款Android手机,那App的界面当然是按照这个标准来做,个人猜测可能这时候在UI中还是用的px做单位。之后2009年1月Kogan推出了正统的全球第二款Android手机——Agora,使用Android 1.5的系统,但搭载的却是2.5英寸,240*320(QVGA)分辨率的显示屏,在加上各种山寨手机,这时问题出现了:分辨率不一样了,而且还有增多的趋势,每个应用得为不同的分辨率发布好几个版本,显然用px定位界面元素已经不适用了,那该用什么来保证一个App在不同的屏幕尺寸下都能运行呢?
其实想一想适配的主要目标是什么,不就是保证不同屏幕上显示的界面元素的百分比相同么。那能直接用百分比来直接指定位置吗?显然不行,首先肯定要考虑到兼容以前的程序,其次用百分比来指定位置也太不准确了。
那我们来从另一个方向来考虑,比如有320*480和480*800两种分辨率的屏幕,为了兼容以前的应用,肯定以320*480的屏幕为标准,那我们考虑如果要保持界面元素的百分比不变,从横向上计算,在320*480屏幕上的一个像素,在480*800的屏幕上应该为1.5个像素才能保持比例,因为480/320=1.5,也就是把480分成了320份,每份1.5个像素。同样对于240的屏幕来说,就是0.75。现在一切看起来都很好,貌似在布局时获取一下分辨率然后进行如上的计算就行了,肯定可以保证显示效果是相同的,但是,要注意到我们用的是像素,显示的最小单位,半个像素是没办法显示的,所以只能进行修正:对结果加上0.5再四舍五入,这就使得不同分辨率显示的效果总会有偏差。
然后,我们再来考虑屏幕尺寸。我们知道分辨率和屏幕尺寸是没有关系的,320*480的分辨率可以做在一块3.5英寸的屏幕上,而640*960的分辨率同样可以做在3.5英寸的屏幕上,相似的,320*480的分辨率可以做在3.5英寸的屏幕上,也可以做在3.2英寸的屏幕上。对于在3.5英寸上320*480屏幕上的一个像素,同尺寸640*960的屏幕就要用2个像素,也和上边的运算一样。
现在我们把上边两种情况综合起来考虑,其实用分辨率除以屏幕尺寸计算出单位长度的像素数,就足以计算百分比了,这个单位长度的像素数就是万恶的屏幕密度。
计算方法就是用屏幕对角线的像素数/屏幕对角线的尺寸(也就是屏幕尺寸)。
所以从Android 1.6开始,Google开始使用屏幕密度的概念来定位界面元素。同样,为了兼容以前的程序,肯定要以以前的屏幕密度做为基准,但计算后却发现G1的屏幕密度其实是180,不是官方定义的160,至于原因,可能是对不同屏幕密度取的一个平均值,但更应该注意到,iPhone的屏幕密度就是赤裸裸的160,我好像发现了什么。
采用屏幕密度以后,定位的单位开始使用dp,而不是px,从Android 1.6开始Google定义了三种屏幕密度:120、160、240。对于160的基准密度屏幕,1dp=1px。而在240的屏幕下,1dp=1.5px。
从此,dp就是屏幕适配的第一个维度,开发人员只需在程序中使用dp指定元素位置,其它的操作都由系统自动完成。
目前来看,这个方法对当时的手机来说应该够用了(2.5英寸到3.5英寸左右,横向都是320dp)。但向长远考虑一下,屏幕的尺寸越来越大怎么办。计算一下,480*800的屏幕如果做到5英寸,那屏幕密度就也是160了,根据基准屏幕的定义,此时1dp=1px,也就是横向会有480dp,而不是320dp,这时若运行以前的应用屏幕右侧肯定会有空白。其实我们考虑一下,大屏幕的初衷就是为了显示更多的内容,如果还是按比例来缩放,显示的内容和小屏幕的相同,那大屏幕就没有意义了。所以,Google引入了屏幕适配的第二个维度——屏幕尺寸。于是,就出现了每个屏幕适配教程都会用到的表:
密度 屏幕大小 |
Low density (120)ldpi |
Medium density (160)mdpi |
High density (240)hdpi |
Small screen 2.5寸到3.2寸 |
240x320 |
|
|
Normal screen 3寸到4.3寸 |
240x400 240x432 |
320x480 |
480x800 480x854 540x960 |
Large screen |
480x800 480x854 |
480x800 480x854 |
|
从Android 1.6开始,Google不仅把屏幕密度分为了高中低三种,还把屏幕尺寸分成了大、小和普通三种。对不同的屏幕尺寸,就可以使用不同的布局文件,如普通尺寸的屏幕就把布局文件放在layout目录中,而大屏幕的布局文件就放在layout-large中,同样小屏幕的布局文件就放在layout-small中,系统会自动根据屏幕尺寸加载对应的布局文件。
但是人们对于大屏幕的追求是无止境的,iPad的推出必然使Android引进更大屏幕的设备,于是在Android 2.3开始,屏幕尺寸增加了超大屏幕(Extra Large Screen)和超高密度(Extra High Density),上表就变成了如今的最终形式:
|
Low density (120), ldpi |
Medium density (160),mdpi |
High density (240), hdpi |
Extra high density (320),xhdpi |
Smallscreen |
QVGA (240x320) |
|
480x640 |
|
Normalscreen |
WQVGA400 (240x400) |
HVGA (320x480) |
WVGA800 (480x800) |
640x960 |
Largescreen |
WVGA800** (480x800) |
WVGA800* (480x800) |
|
|
Extra Largescreen |
1024x600 |
WXGA (1280x800)† |
1536x1152 |
2048x1536 |
如此,二维布局适配大法最终成型了,此法由两个维度来适配屏幕,横向维度由系统自动控制,纵向维度通过布局文件指定。
在如此完美的方案下,Google还是觉的不够,尤其是在平板上,每一寸的空间对UI都是至关重要的。所以在Android 3.2,Google又引入了新的布局限定符:sw<N>dp、w<N>dp、h<N>dp。N用来指定dp数,如layout-w720dp,系统会在当前宽度最少为720dp的条件下加载此目录下的资源文件,这比用layout-xlarge-land更精确。
如此,布局文件算是告一段落。但界面上的元素除了控件,更多的恐怕是图片。对同尺寸的图片,放在低密度屏幕上会很大,而放在高密度屏幕上会很小,这明显不符合保持百分比不变的理念。所以,Android会根据设备的屏幕密度,自动放大或缩小的图片,使得在不同密度的屏幕上看起来大小是相似的,这虽然方便,但图片的放大和缩小会造成失真,这对制作漂亮的UI是个嚣张的挑战。所以借鉴布局的做法,Google对图片按照屏幕密度进行了分类,如:drawable-ldpi、drawable-mdpi、drawable-hdpi等,系统会根据不同的密度加载对应目录下的图片。而对于实在是不想进行缩放的图片,可以放在drawable-nodpi。因为四种屏幕密度是有比例的,所以官方建议图片的比例为3:4:6:8。
第二部分对开发人员的建议
借鉴官方的Best Practices,对开发人员在适配中提几点建议:
1、充分利用Layout的特性,比如居中,与其费劲去计算margin,不如用RelativeLayout的center来的方便,并且可以适配各种屏幕。
2、充分利用控件的属性,什么wrap_content,fill_parent,能让系统计算的就让系统去计算,尤其是layout_weight,用的适当可以产生很好的适配效果。
3、指定位置一定要用dp,不要用像素值。而且对于不同屏幕需要指定不同位置的情况来说,请使用dimen。因为values也是可以指定屏幕的,如values-normal-hdpi。
4、不要使用AbsoluteLayout,这是官方说的。
5、对平板和手机,还是做两个版本吧,就平板所提供的图片资源就不是手机能受的了的。更别说为了适配要建立多少资源目录了。
6、和设计人员多沟通,利用好.9.png的图片,可以节省不少时间和空间。
7、字体大小使用sp。
第三部分对设计人员的建议
1、要理解用dp取代px的原因,最好能理解适配中所采用的一般方法。
2、对不同的屏幕密度提供切图,注意要保持比例。
3、最好能按照屏幕密度为160的尺寸做效果图,这样开发人员在开发过程中可以进行1:1的比对。