给你一个全自动的屏幕适配方案(基于 SW 方案)!
为不同的屏幕尺寸提供不同的布局 默认情况下,Android 会调整应用的布局大小以适应当前设备的屏幕,大多数情况下系统提供的支持就能满足我们的需要。但是有时候需要针对不同的屏幕分辨率来设计不同的布局,以达到更好的现实效果。
为不同的屏幕密度提供不同的图片资源 我们可以通过配置密度资源的配置限定符来提供不同像素的图片,来适配不同的屏幕密度。
对于第一点,在实际工作中是很难实现的。因为一般 UI 只会提供一套设计稿,不会根据不同分辨率的屏幕来提供相应的适配。但是我们没办法控制我们的 App 最终会运行在什么分辨率的屏幕上,为了达到在不同屏幕上的显示效果一直,我们可以通过提供不同密度的位图资源与 Smallest Width 方案来实现屏幕适配。
什么是 Smallest Width 适配
Smallest Width 字面上的意思就是最小宽度,由可用屏幕区域的最小尺寸指定。 具体来说,设备的 smallestWidth 是屏幕可用高度和宽度的最小尺寸。
例如,如果布局要求屏幕区域的最小尺寸始终至少为 600 dp,则可使用此限定符创建布局资源 res/layout-sw600dp/
。仅当可用屏幕的最小尺寸至少为 600dp 时,系统才会使用这些资源,而不考虑 600dp 所代表的边是用户所认为的高度还是宽度。smallestWidth 是设备的固定屏幕尺寸特性;设备的 smallestWidth 不会随屏幕方向的变化而改变。
所以我们可以根据需要适配的屏幕的 sw 值来提供不同的资源来实现屏幕适配。
UI 设计与屏幕适配的一些基础理念
我觉得很多屏幕适配教程都漏了一个很重要的点,就是:没有解释清楚屏幕适配与 UI 设计之间的关系!
一般在实际开发的时候,UI 设计师都会提供一套 UI 稿与标尺,工程师是通过这套标尺来开发 UI 的。UI 如果我们要做好 Android 的屏幕适配,那么我们必须要明白的一点就是,UI 稿在我们进行界面开发中是充当锚点的作用的。要适配其它的屏幕的话,必须要以这个基准为基础计算其它屏幕的 dimens 资源的值。
举个例子: 例如,很多 UI 设计师都会以 iPhone6 的尺寸作为标准来制作设计稿与标尺的,而 iPhone6 的屏幕宽度为 375px,所以这个宽度为 375px 的设计稿就是我们屏幕适配的基准了。
假设有一台 sw 等于 375dp 的设备的话,那么这个设备与设计稿对应的关系就是 1dp = 1px,那么我们就不需要进行任何适配,直接把设计稿以 px 为单位的标尺值以 1:1 的比例转换成以 dp 为单位就可以了。
在这里,我们可以得出一个结论就是:屏幕适配需要以 UI 稿为基准再制定合适的适配方案!
但是有一个问题就是,每个 UI 设计师的喜好都是不一样的,提供的设计稿的比例尺也不是固定的。而且 Android 的屏幕碎片化非常严重,我们需要适配的屏幕的 sw 的值也是变化多端的。所以如果每次都需要手动计算对应的 dimens 值的话,非常耗时间与繁琐。网上提供了一些工具来快速生成对应 sw 的 dimens 值,但是这些工具都会存在两个缺点:
没办法根据 UI 设计稿来转换,所以不一定能 100%还原设计稿效果
会生成大量无用的 dimens 值。其实如果我们细心观察过设计稿的话,我们会发现,其实每份设计稿常用的 px 值都是固定的十来个。例如同样以 375px 的设计稿为基准的话,使用工具会生成 1px ~ 375px 对应的 dp 值,所以会存在大量的无用 dimens 值。这样只会徒增安装包的大小。
这个两个缺点,可以使用笔者的 calces.screen 插件来解决,下文会介绍这个插件的使用方法与使用效果的。
使用 calces.screen 快速实现 Smalles Widths 适配方案
适配前与适配后对比情况
还是以 iPhone6 的设计稿为例子,假如有下面这么一副设计稿,如果不进行任何适配的话,在不同的设备上的显示效果对比如下:
第一个手机就是上文中说到的 sw = 375dp 的手机,我们可以看到 sw 为其他值的手机上面,显示效果都不如意。在 sw = 411dp 和 sw = 900dp 的设备上,都留有大量的空白空间,而在 sw = 360dp 的设备上,则有超出屏幕
范围的现象。我们适配的目标就是:达到所有设备上显示的效果都和设计稿(sw = 375dp 上的效果)一致。
使用 calces.screen 插件适配后的效果如图所示:
这里有一点需要注意的是,可以看到第三台设备里面的适配还是有点问题,大概留下了 1dp 左右的白边。这个是 pixel 2 XL 的模拟器,可以看到,测量出来的 sw 值应该是 411dp 的,但是经过笔者的实际测量,发现 sw 应该是 412dp 才对。有兴趣的读者可以自己在布局编辑器里面创建一个 width 为 411dp 的控件,可以看到在 pixel 2 XL 设备下也是有大概 1dp 的白边的。所以这个 1dp 的误差应该是和设备有关的,这里贴上用 calces.screen 生成的 sw = 411dp 的 dimens 文件的值观大家参考。
当 sw = 411dp 时,px_375 的实际值时 411dp,所以这是符合我们的预期转换结果的。
如何引入 calces.screen
首先,我们需要引入 calces 插件,引入的方式很简单:
在项目的 build.gradle 中添加代码:
//Gradle 版本高于 2.1 的情况下(推荐方案)plugins {id "calces.screen" version "1.2.3"}
//Gradle 版本低于 2.1 的情况下(2.1 以上版本也兼容这种方式)buildscript {repositories {maven {url "https://plugins.gradle.org/m2/"}}dependencies {classpath "gradle.plugin.com.tangpj.tools:calces:1.2.3"}}
在 modules 的 build.gradle 中添加代码:
apply plugin: "calces.appconfig"
使用 calces.screen 适配屏幕
首先,我们需要在 res/values/文件夹中创建 dimens.xml 文件,然后按照设计稿的标尺把需要用到的尺寸写到该文件下。例如:
这就是我们的基准 dimens 文件。
现在我们只需要把基准尺寸与需要适配的尺寸通过 Gradle 配置就可以了,例如,上面的例子中,我们需要适配的 sw 有:320dp, 411dp, 900dp,那么我们需要在 modules 的 build.gradle 文件下添加如下代码:
screen{
dimens{designPx 375smallesWidths 320,375,411,900scale BigDecimal.ROUND_UPauto true}
}
上面配置信息的对应关系是:
designPx:设计稿的 sw 尺寸(单位 px)
smallesWidths:需要适配的屏幕 sw 尺寸(单位 dp)
scale: 数字取整的方式 因为 Android 系统只能适配整数单位的 dp 值,所以我们可以通过 scale 来配置具体的取正方式。这里直接取 BigDecimal 提供的 round 来实现。如果不设置的话,则会生成 double 类型的 dp 值(实际使用的时候会丢弃小数位)
auto:是否自动生成 dimens,当 auto 为 true 时,每次 build 都会重新生成一次适配 dimens 文件。 如果不设置 auto 或设置为 false 的话,可以手动调用 gradle 任务来生成。 调用命令: /gradlew dimensCovert 也可以直接点击 gradle 任务执行,方式如下图:
配置完毕后,重新 build 以下项目就可以看到生成的资源文件了,如下图:
为了不影响编译时间 auto 建议设置为 false,需要的时候再手动启动任务生成适配资源文件。
如何确定我们需要适配什么 sw 值?
除了自动生成 sw 外,我们还需要确定,我们的 App 需要支持那些 sw 值。最简单的方法就是,先确定我们要支持哪些设备。这里笔者给出一个建议就是,市面上有非常多设备的 sw 值都是 360dp 的,所以我们必须要适配 360dp 的设备。至于其它的设备,我们可以这样来确定,在开发者模式里面找到一项叫做最小宽度的参数,里面的值就是我们需要的 sw 值。具体如下图:
例如,上面这个是 Nexus S 的 sw 值。如果我们不专门适配 sw = 384dp 的屏幕的话,那么系统就会默认寻找低于 384dp 的适配资源(所以 360dp 是一个相对通用的适配值)。当我们拥有测试设备的时候,使用 calces.screen 适配是非常简单的。那么如果我们不知道没有测试设备呢?(例如有用户反馈,某个设备下的适配有很大问题)
这里给大家推荐一个网站:Device Metrics
这个网站是 Material Design 的设备参数查找网站,用户在这里直接找到对应设备的尺寸就可以了(之前的方法翻车了,溜了溜了)。
一般情况下,sw 为 360dp 和 480dp 的屏幕会比较常见,所以我们必须要生成这两套资源,如果需要支持 Pad 的话,则需要适配 sw = 600dp 或 sw = 720dp 的屏幕,然后再根据实际情况适配其它 sw 值的屏幕。
到这里为止,我们就完成了 Android 基于 sw 方案的屏幕适配了,非常简单!
但是,本文还没结束,这个插件除了提供自动实现基于 sw 方案的适配外,还提供了一个杀手级功能:根据配置自动把生成对应分辨率的位图资源。当我们需要适配多种不同屏幕密度的手机的时候,只需要提供一套高清位图资源就可以了,解放你和 UI 设计师的双手。
calces.screen 实现位图自动缩放适配
为不同密度的屏幕提供不同的位图资源是 Google 官方推荐的屏幕适配做法。这样做的好处是,能使 App 在不同密度的屏幕上都能达到最好的效果,不会出现在高清屏下出现老年机的显示效果,并且在不同密度的屏幕下都能保持相对稳定的显示效果。下面是位图资源密度对应的比例关系:
但是这里会产生一个问题,一般情况下,位图资源是 UI 设计师提供给我们的。我和很多 UI 设计师讨论过,他们的方案就是先切一套最高清的图片,然后再根据需要进行缩放,然后提供给工程师使用。
一般情况下,这种做法除了繁琐点也没什么问题。但是如果现在出现了一个情况,就是需要支持更低密度的屏幕呢?这种情况只能让 UI 设计师再缩放一套密度的位图。那如果某部分位图已经不再使用了,需要删除呢?那工程师需要把其它密度的位图找出来再删除。而且再往工程里面添加新的位图的时候也需要手工添加。
所以一般情况下,UI 提供图片资源 —— 工程师使用图片资源这个过程中是纯手工控制的。工作非常繁琐并且没什么意义,而且手动迁移的过程中还非常容易出错(想想如果复制漏了某几个密度的位图资源会是什么画面?)。所以 calces.screen 还提供了位图管理功能。
评论