我们知道屏幕适配一直都Android开发中的痛,因为机型的种类,屏幕类型数不胜数,所以在适配不同的手机的时候,如何才能最低成本的适配各种各样的手机,成为的我们一直关注的问题,下面我就一一介绍不同屏幕适配方案,当然,也会先介绍为什么会出现屏幕适配的背景知识。
知识点汇总:
一:屏幕适配的基本知识
二:直接dp适配
三:宽高限定符适配适配
四:鸿神 的 AndroidAutoLayout方案适配
五:今日头条适配方案适配(推荐)
六:smallestWidth适配,或者叫sw限定符适配(推荐)
七:扩展阅读
一:屏幕适配的基本知识
这里我首先需要介绍三个公式,希望各位读者可以根据自己现在手上的手机,也动手套用一下这三个公式,以便更好的了解这三个公式。
公式一:
通过上面的公式,可以算出自己手机当前的DPI的值,由于不同的手机DPI的值是不一样的,而不同DPI的手机会动态加载不同文件夹下面的资源,请看下图:
从上面谷歌官方提供的两张截图,可以知道,不同范围的DPI手机,会加载不同文件夹下面的资源,并可以区分不同屏幕大小类型。
公式二:DPI / 160 = density
通过公式二,可以知道一个类似屏幕密度的变量。
公式三:dp = px / density,屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度。
通过公式三,我们可以获得手机的宽和高的总dp值,注意这里px的值,分别是屏幕的总宽像素 和 屏幕的总高像素,而且这里需要注意,px与dp的值的关系,与我们在写界面时dp与px的关系不是一个概念的东西,需要特别注意,且值刚好相反。
二:直接dp适配
通过上面的公式,我们了解到不同的屏幕对相同的控件会显示不同的效果。
方案缺点:举个例子:设备 1,屏幕宽度为 1080px,480DPI,屏幕总 dp 宽度为 1080 / (480 / 160) = 360dp,设备 2,屏幕宽度为 1440,560DPI,屏幕总 dp 宽度为 1440 / (560 / 160) = 411dp。
可以看到屏幕的总 dp 宽度在不同的设备上是会变化的,但是我们在布局中填写的 dp 值却是固定不变的
这会导致什么呢?
假设我们布局中有一个 View的宽度为 100dp,在设备 1 中 该 View的宽度占整个屏幕宽度的 27.8%(100 / 360 = 0.278) 但在设备 2 中该 View的宽度就只能占整个屏幕宽度的 24.3%(100 / 411 = 0.243),可以看到这个 View在像素越高的屏幕上,dp值虽然没变,但是与屏幕的实际比例却发生了较大的变化,所以肉眼的观看效果,会越来越小,这就导致了传统的填写 dp的屏幕适配方式产生了较大的误差。
这时我们要想完美适配,那就必须保证这个 View在任何分辨率的屏幕上,与屏幕的比例都是相同的。
三:宽高限定符适配适配
生成的目录如下图:
就是这种,在资源文件下生成不同分辨率的资源文件,然后在布局文件中引用对应的 dimens。
特别注意,我们这里是以320*480为基准的,如果基准选择不一样,文件里面生成的值也是不一样的。
下面推荐两个自动生成values文件夹,这里推荐两个工具:
1、AndroidPixelDimenGenerator
2、张鸿洋大神写的autolayout.jar这个工具:https://github.com/hongyangAndroid/Android_Blog_Demos/tree/master/blogcodes/src/main/java/com/zhy/blogcodes/genvalues
这个时候,如果我们的UI设计界面使用的就是基准分辨率,那么我们就可以按照设计稿上的尺寸填写相对应的dimens引用了,而当APP运行在不同分辨率的手机中时,这些系统会根据这些dimens引用去该分辨率的文件夹下面寻找 对应的值。这样基本解决了我们的适配问题,而且极大的提升了我们UI开发 的效率。
方案缺点:
1、这个方案有一个致命的缺陷,那就是需要精准命中才能适配,比如1920x1080的 手机就一定要找到1920x1080的限定符,否则就只能用统一的默认的dimens文件 了。而使用默认的尺寸的话,UI就很可能变形,简单说,就是容错机制很差。 不过这个方案有一些团队用过,我们可以认为它是一个比较成熟有效的方案了。
2、由于实际上还是使用px作为长度的度量单位,所以和google的要求使用dp作为 度量单位会有所背离。
3、过多的分辨率像素描述xml文件会增加软件包的大小和维护的难度。
四:鸿神 的 AndroidAutoLayout方案适配
使用方法:
第一步: 在你的项目的AndroidManifest中注明你的设计稿的尺寸。
<meta-data android:name="design_width" android:value="720">
</meta-data>
<meta-data android:name="design_height" android:value="1280">
</meta-data>
第二步:
让你的Activity继承自AutoLayoutActivity.然后我们就可以直接在布局文件里面 使用具体的像素值了,比如,设计稿上是96*96,那么我们可以直接写96px,APP 运行时,框架会帮助我们根据不同手机的具体尺寸按比例伸缩。
这可以说是一个极好的方案,因为它在宽高限定符适配的基础上更进一步, 并且解决了容错机制的问题,可以说完美的达成了开发高效和适配精准的两个要求。
方案缺点:
1、因为框架要在运行时会在onMeasure里面做变换,我们 自定义的控件可能会被影响或限制,可能有些特定的控件,需要单独适配, 这里面可能存在的暗坑是不可预见的,还有一个比较重要的问题,那就是整个 适配工作是有框架完成的,而不是系统完成的,一旦使用这个框架,未来一旦 遇到很难解决的问题,替换起来是非常麻烦的,而且项目一旦停止维护,后续 的升级就只能靠你自己了,这种代价团队能否承受?当然,它已经停止维护了。
2、由于实际上还是使用px作为长度的度量单位,所以和google的要求使用dp作为 度量单位会有所背离。
五:今日头条适配方案适配(推荐)
原理:今日头条屏幕适配方案的核心原理在于,根据以下公式算出 density当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density density 的意思就是 1 dp 占当前设备多少像素。
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density 这个公式就是把上面公式中的屏幕的总 dp 宽度换成设计图总宽度,原理都是 一样的,只要 density 根据不同的设备进行实时计算并作出改变,就能保证设计 图总宽度不变(总宽度dp保持不变),也就完成了适配。
不同分辨率的设备都完成了等比例缩放,证明今日头条屏幕适配方案在不同 分辨率的设备上都是有效的。
方案优点:
1、使用成本非常低,操作非常简单,使用该方案后在页面布局时不需要额外的代码和操作,这点可以说完虐其他屏幕适配方案。
2、侵入性非常低,该方案和项目完全解耦,在项目布局时不会依赖哪怕一行该 方案的代码,而且使用的还是 Android 官方的 API,意味着当你遇到什么问题无 法解决,想切换为其他屏幕适配方案时,基本不需要更改之前的代码,整个切换 过程几乎在瞬间完成,会少很多麻烦,节约很多时间,试错成本接近于 0。
3、可适配三方库的控件和系统的控件(不止是 Activity 和 Fragment,Dialog、 Toast 等所有系统控件都可以适配),由于修改的 density 在整个项目中是全局 的,所以只要一次修改,项目中的所有地方都会受益 。
4、不会有任何性能的损耗。
下面是头条官方给出的图片,适配前后和设计图对比:
适配后各机型的显示效果:
方案缺点:
1、这个方案依赖于设计图尺寸,但是项目中的系统控件、三方库控件、等非我们项目自身设计的控件,它们的设计图尺寸并不会和我们项目自身的设计图尺寸 一样当这个适配方案不分类型,将所有控件都强行使用我们项目自身的设计图尺寸 进行适配时,这时就会出现问题,当某个系统控件或三方库控件的设计图尺寸和和 我们项目自身的设计图尺寸差距非常大时,这个问题就越严重。
解决方案:
1、调整设计图尺寸,因为三方库可能是远程依赖的,无法修改源码,也就无法 让三方库来适应我们项目的设计图尺寸,所以只有我们自身作出修改,去适应三 方库的设计图尺寸,我们将项目自身的设计图尺寸修改为这个三方库的设计图尺 寸,就能完成项目自身和三方库的适配。
2、第二个方案是最简单的,也是按 Activity 为单位,取消当前 Activity 的适配 效果,改用其他的适配方案。
推荐开源项目:1、https://github.com/JessYanCoding/AndroidAutoSize
六:smallestWidth适配,或者叫sw限定符适配(推荐)
描述:smallestWidth适配,或者叫sw限定符适配。指的是Android会识别屏幕可用高度和宽度的最小尺寸的dp值(其实就是手机的宽度值),然后根据识别到 的结果去资源文件中寻找对应限定符的文件夹下的资源文件。
这种机制和上文提到的宽高限定符适配原理上是一样的,都是系统通过特定 的规则来选择对应的文件。
根据设计图填写最小宽度基准值,并填写需要适配的设备最小宽度 dp 值, 例如设计图的最小宽度为 375dp,则需要更改最小宽度基准值为 375dp。如果 项目只需要适配手机的话,适配的设备最小宽度保留 320,360,384,392,400,410,411,480 即可。
使用:1、以设计图最小宽度(单位为 dp)作为基准值,利用插件生成所有设备 对应的 dimens.xml 文件 2、根据设计图标注,标注多少 dp,布局中就写多少dp,格式为@dimen /dp_XX。
举个例子:
小米5的dpi是480,横向像素是1080px,根据px=dp(dpi/160), 横向的dp值是1080/(480/160),也就是360dp,系统就会去寻找是否存在 value-sw360dp的文件夹以及对应的资源文件。
现在的手机主要集中在320dp-480dp间,建议在此区间,没间隔10dp,生成一个文件夹,这样可以更好的适配不同的手机。
我们还有以375个像素宽度的设计稿为例,在values-sw360dp文件夹下的diemns文件应该怎么编写呢?这个文件夹下,意味着手机的最小宽度的dp 值是360。
项目资源目录结构:
包含(包含了平板和 TV )
dimens文件生成:
1、Android Studio 中安装 ScreenMatch 插件
2、github轮子:https://github.com/wildma/ScreenAdaptation
方案优点:
1、smallestWidth限定符适配和宽高限定符适配最大的区别在于,前者有很好的 容错机制,如果没有value-sw360dp文件夹,系统会向下寻找,比如离360dp 最近的只有value-sw350dp,那么Android就会选择value-sw350dp文件夹下面 的资源文件。这个特性就完美的解决了上文提到的宽高限定符的容错问题。
2、如果只适配手机,dimens.xml 文件所占的体积只有 100 多 KB,即使加上 平板和 TV,也就500多KB,完全可以接受。
上面基本上介绍了目前市面上常见的屏幕适配方案,相信大家对屏幕适配都有了新的认识了吧,希望大家在后续的项目中,能尝试一下新的屏幕适配方案,我这里推荐今日头条适配方案和sw限定符适配。
七:扩展阅读
1、https://www.jianshu.com/p/7aa34434ad4d(Android适配全面总结 (一)----屏幕适配)
2、https://www.jianshu.com/p/55e0fca23b4f?utm_source=oschina-app(骚年你的屏幕适配方式该升级了!-今日头条适配方案)
3、https://blog.csdn.net/guofudong2/article/details/81286734(AndroidUI 屏幕适配)
4、https://www.jianshu.com/p/2aded8bb6ede(骚年你的屏幕适配方式该 升级了!-SmallestWidth 限定符适配方案)
5、https://www.jianshu.com/p/1302ad5a4b04(一种非常好用的Android 屏幕适配)
6、https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA(一种极低成 本的Android屏幕适配方式,头条官方文档)
网友评论