原文地址:https://yuriypikachu.github.io/2020/02/15/如何优雅进行的Android的屏幕适配/
无论你要出去面试,还是身为一个移动开发工程师。屏幕适配是客户端最经常碰到的问题,因此掌握客户端的屏幕适配是一个基本能力,优雅的屏幕适配,可以保证你还原设计稿的同时,还可以节约你的开发成本,该方案最终 5 行代码就可以实现屏幕适配。
来自备不同分辨率的机型2种: 机型A:720*1280 320dpi 5.5英寸(pixel 2)
机型B:1080*1920 420dpi 5.0英寸
首先我们先计算铺满机型A的宽度是多少dp? 因为:计算公式px = dp * (dpi / 160) 又因为:机型A宽度是720PX,机型A的dpi是320dpi。 所以:dp = px/(dpi/160) = 720/(320/160) = 360dp 结论:我们铺满一个机型A需要360dp。
最后布局如下:
机型A上的展示:
机型B上的展示:
同样的一个TextView,宽度为360dp,在机型A上是铺满的。在机型B上却是留有空白。因此,在开发过程中,为了还原设计稿的样式,我们就需要统一的方案来进行适配。当设计师设计一套样式的时候,至少保证所有的设计稿,在宽度的百分比上是一致的。
在res下面创建多套dimens.xml 文件如下:结论:非常不优雅,而且工作量特别大,设计稿只有一套,你要自己想办法拿到其他分辨率的设计稿宽高,而且会让适配工作没法收敛。
首先我们要懂一点,无论是我们 Android 用 dp,pt,sp 还是其他,最后系统代码都会通过 density 把他们转换成px展示在屏幕上。
因为我们在每个 View 的宽度,高度等都是填入 dp 值,那我们只要保证每个机型的屏幕总 dp 宽度不变,就能保证每个 View 在所有分辨率的屏幕上与屏幕的比例都保持不变,从而完成等比例适配,并且这个屏幕总 dp 宽度如果还能保证和设计图的宽度一致的话,那我们在布局时就可以直接按照设计图上的尺寸填写 dp 值。
dp = px/density
在这个公式中我们要保证屏幕的总 dp 宽度 和 设计图总宽度一致,且在所有分辨率的屏幕上都保持不变,我们需要怎么做呢?屏幕的总 px 宽度 每个机型都不一致,这个值是肯定会变化的,因此我们再用一下上述公式:
因为:dp = px/density 所以:density = px/dp 又因为:我们把设计图的宽度等于手机的宽度 所以:density = 机型屏幕总宽度(px)/ 设计图总宽度(dp)
回到开头的问题,假设机型机型A的宽度就是设计图总宽度为 360 dp,那我们这时候带入公式去验证机型B?
一个 TextView 在这个设计图上的尺寸是 360dp * 120dp,这个 View 的宽度占整个机型A宽度是100%。
机型B,屏幕总宽度为 1080 px,根据公式求出 density = 机型屏幕总宽度(px)/ 设计图总宽度(dp) = 1080 / 360 = 3 这个 360dp * 120dp 的 TextView,系统最后会将高宽都换算成 px = dp * density = 360dp * 3 = 1080 px ,通过该方案也铺满了机型B。
采用kotlin实现的代码
机型A:机型B:
因此,我们通过该方案,实现了屏幕适配。
1、使用成本特别低,操作相当简单,使用该方案后在页面布局时不需要额外的代码和操作。
2、侵入性非常低,该方案和项目完全解耦,在项目布局时不会依赖哪怕一行该方案的代码,而且还是 Android 官方的 API,意味着当你遇到什么问题无法解决,想切换为其他屏幕适配方案时,基本不需要更改之前的代码,整个切换过程几乎在瞬间完成,会少很多麻烦,节约很多时间,试错成本接近于 0,不会有任何性能的损耗。
3、可适配三方库的控件和系统的控件(不止是 Activity 和 Fragment,Dialog、Toast 等所有系统控件都可以适配),由于修改的 density 在整个项目中是全局的,所以只要一次修改,项目中的所有地方都会受益。
1、只需要修改一次 density,项目中的所有地方都会自动适配,这个看似解放了双手,减少了很多操作,但是实际上反应了一个缺点,那就是只能一刀切的将整个项目进行适配,但适配范围是不可控的。
2、这样不是很好吗?这样本来是很好的,但是应用到这个方案是就不好了,因为我上面的原理也分析了,这个方案依赖于设计图尺寸,但是项目中的系统控件、三方库控件、等非我们项目自身设计的控件,它们的设计图尺寸并不会和我们项目自身的设计图尺寸一样。
3、当这个适配方案不分类型,将所有控件都强行使用我们项目自身的设计图尺寸进行适配时,这时就会出现问题,当某个系统控件或三方库控件的设计图尺寸和和我们项目自身的设计图尺寸差距非常大时,这个问题就越严重。
demo 地址,欢迎点star:https://github.com/YuriyPikachu/AutoSizeDemo