屏幕适配的必要性

  1. 处理虚拟尺寸和设计稿之间的比例,如设计稿为375 x 667,我们需要将这个尺寸缩放到我们的虚拟尺寸上。
  2. 处理个别手机虚拟尺寸不同的问题,让虚拟尺寸不同的手机显示相同的视觉效果。

何为虚拟尺寸

我们采用Android中的dp来作为单位来描述虚拟尺寸。下面先来解释下dp。

概念解释

我们需要先看下下面的几个定义:

  • 像素(PX): 屏幕上的物理点,是显示图像的最小单元。
  • 每英寸像素密度(DPI): 每英寸中的像素个数。
  • 密度无关像素(dp, dip): Android中定义的虚拟尺寸

Android设备的历史发展

在最早的手机上(即一倍屏 Size=360px * 640px, Density=160dpi),1dp=1px。

所以我们的虚拟尺寸为360dp * 640dp。

由此我们推倒出虚拟尺寸的计算公式:

宽/高度 = Size(宽/高度) / (Density / 标准Density(160))

之后又出现了二倍屏(Size=720px * 1280px, Density=320dpi)和三倍屏(Size=1080px * 1920px, Density=480dpi)

经过计算,他们的虚拟尺寸同为360dp * 640dp

所以,一定程度上dp这个设计还是成功的,它屏蔽了物理尺寸之间的差异,在不同尺寸屏幕的设备上显示了相同的效果。

存在虚拟尺寸不是360dp*640dp的手机么?

存在的,比如坚果Pro2,它的虚拟尺寸进过计算为430dp*800dp,一个360dp的色块在小米和坚果手机上显示如下:

这样直接写dp就会变小了,我们下面讲下虚拟尺寸的适配,把这个坚果手机的显示效果适配的和小米一样。

适配虚拟尺寸

使用资源描述符机制

根本原理还是得通过Android提供的资源描述符机制进行,这里我们选用sw,即需要生成一个values-swXXXdp的资源目录。

我们的程序跑在这样的手机上时,会去先寻找sw和自身属性匹配的目录。找不到的话在从 统一的values.xml进行寻找。

如一个宽度为400dp的手机,会去寻找sw-400dp或者w-400dp的资源目录。

这样的方式需要我们手动将写多个dimens.xml文件,能否自动化呢? 下面介绍下。

使用Gradle Plugin自动生成sw文件

原理

先了解下Android资源的编译流程,在编译时,资源会被merge到统一的目录,然后在被AAPT所处理,我们在AAPT处理之前,在资源Merge之后将尺寸文件进行生成即可。

下面看下我们的Hook点,AAPT处理资源的Task叫ProcessVariantResource。我们将自定义的Task先于它执行即可。

将我们资源处理Task Hook进编译流程

代码也非常简单

我们的Task目前处于这个位置 暂且命名为MergeVariantDimensResource

通过自定义Task处理资源

然后使用Groovy将values.xml中的<dimens>标签读取处理,在指定sw的目录生成重新生成values.xml文件,并重新计算尺寸。

适配效果如下,这样就和之前的小米手机显示一样了:

对于我们来说侵入性并不强,只是需要在dimens.xml中指定下尺寸而已。

Task代码

并没有什么很复杂的逻辑,大部分都是xml操作。

定义一个Ext,供传入参数

插件代码:

发表评论

电子邮件地址不会被公开。 必填项已用*标注