稀有猿诉

十年磨一剑,历炼出锋芒,说话千百句,不如码二行。

适配多屏幕的最佳实践

对于Android应用开发来讲,比较头疼的,也是比较重要的一个工作就是要尽可能多的支持市场上的Android设备,由于Android的开放性,各种奇奇怪怪的设备都有,符合标准的,不符合标准的,行货,水货,山寨货鱼龙混杂,防不胜防。为了让我们的应用能够得到尽可能多的用户,我们就必须能让应用以超强的适应性,以能在混乱的手机里生存。而适配设备,GUI屏幕的适配又是重中之中,如果用户都无法正确的看到你的UI页面,那还用个毛线啊!

之前曾经写过一篇文章,介绍了一下子如何使用dimen资源来适配多屏幕,随着Android版本的演进,有些概念已经过时,需要重新整理一下。

其实对于多屏幕适配,一个核心的原则就是要对布局做好抽象的分离,把可变与不可变分开,把与屏幕相关的尺度dimen写在单独的dimen文件中,然后使用引用。如果不这样做,就会造成更多的代码重复。

以最佳的方式来提供资源

通常我们的做法是以屏幕密度(Screen Density),做为区分来提供不同的资源,以达到支持和适配不同的屏幕,比如我们会为mdpi, hdpi, xhdpi,各准备一套图片和dimen,大多数情况下,这很好,能对付了大多数设备,但这还不够。

比如说,480x800, 480x854, 540x960这三种设备,都是同样的屏幕密度hdpi,但是屏幕尺寸并不相同,对于qHD(540x960),它的可用空间要比标准hdpi(480x800)要多得多,如果以qHD为基准来调的布局,那么放到480x800上,有些元素会被挤扁,或者显示不完全。而且目前,540x960的设备要多于480x800的,因为屏幕都是越来越大,精度越来越高的。

那么如何解决呢? 现在推荐的做法是用屏幕的可用高度(注意是可用高度,不包括状态栏和底部硬键)来区分不同的资源。以前是可以在屏幕密度后面指定具体的分辨率来区分,比如values-hdpi-960x540。但是现在这种做法已被废弃,官方文档中都不会提及了。很显然它的问题在于不够通用。

现在推荐的做法是用可用高度或者可用宽度来指定:

  • values-h<sw>dp
  • values-h<sh>dp

这里面的sw和sh就是屏幕的可用宽度和可用高度。这种方式的适配规则是:用小于且最接近设备屏幕高度或宽度的那个资源,比如设备可用高度是610dp,则选择values-h600dp,以此类推。用这个方式就能区分同为hdpi的480x800和540x960,因为:

  • 480x800 533dp
  • 540x960 640dp

所以,可以用values-h600dp来区分二者。 使用此的方法为:

  • 计算某个设备的高度或者宽度,以dp为单位。高度dp=可用高度px/density
  • 创建可以区分不同设备的资源目录,如values-h500dp, values-h600dp等

增加适配性的更多技巧

除了上面提到的,还有一些在适配时需要注意的事情。

  1. 尽量多用WRAP_CONTENT和MATCH_PARENT,特别是对于像文字图片等元素的度量
  2. 对于页面的边框距离,最好用最外层的ViewGroup来指定,或者使用margin或者使用padding。 这点的主要意思是,如果你想要页边框距是20dip,那么用一个ViewGroup来指定,要么是最外层的,要么是最里层的,千万不要是外面的5dp,中间的5dp,里面的5dp,最里面的5dp,虽然整体效果看起来是一致的,但是当适配时就会蛋疼了。固定在某个上面,这样既方便调试,也方便适配和移植。
  3. 同一个应用,边框距等最好做到一致,起码对于同一类型的页面更是如此。

一些常见设备的参数

  • 320x480 1 mdpi 480dp
  • 480x800 1.5 hdpi 533dp
  • 540x960 1.5 hdpi 640dp
  • 720x1280 2 xhdpi 640dp
  • 1080x1920 3 xxhdpi 640dp

参考

Comments