Android屏幕适配-今日头条适配方案

在Android开发中,由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高。虽然Android官方提供了dp单位来适配,但其在各种奇怪分辨率下表现却不尽如人意,因此下面探索一种简单且低侵入的适配方式。


Android中的dp在渲染前会将dp转为px,计算公式为:
px = density dp
density = dpi / 160
px = dp
(dpi / 160)

屏幕尺寸、分辨率、像素密度三者关系

通常情况下,一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系为:

举个例子:屏幕分辨率为:1920 * 1080,屏幕尺寸为5寸的话,那么dpi为440 (2203px / 5 = 440)

这样会存在什么问题呢 ?

假如入我们的UI设计图是按屏幕宽度为360dp设计的,那么上述设备中,屏幕宽度其实为1080/(440/160)= 392.7dp
也就是屏幕要比设计图要宽的,这时就会导致按360dp宽度来开发实际显示不全的情况。

梳理需求

首先来梳理一下我们的需求,设计图都是以固定的尺寸来设计的。
比如以分辨率1920px 1080px,以density为3来标注(这个density是设计自己衡量的,取决于屏幕尺寸)那么此时屏幕其实是640dp 360dp。
开发拿到设计图1920px 1080px,还有dpi,就可以计算出density,从而计算出设计图的dp单位:640dp 360dp。

找兼容突破口

从dp和px的转换公式:px = dp * density
可以看出,如果设计图宽为360dp,想要保证在所有设备计算得出的px值都正好是屏幕宽度的话,我们只能修改 density 的值。

屏幕适配核心原理在于,根据以下公式算出 density
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
density 的意思就是 1 dp 占当前设备多少像素。

大家都知道,不管你在布局文件中填写的是什么单位,最后都会被转化为 px,系统就是通过上面的方法,将你在项目中任何地方填写的单位都转换为 px 的。
所以我们常用的 px 转 dp 的公式 dp = px / density,就是根据上面的方法得来的,density 在公式的运算中扮演着至关重要的一步。
我再来说说 density,density 在每个设备上都是固定的,DPI / 160 = density,屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度
设备 1,屏幕宽度为 1080px,480dpi,屏幕总 dp 宽度为 1080 / (480 / 160) = 360dp
设备 2,屏幕宽度为 1440,560dpi,屏幕总 dp 宽度为 1440 / (560 / 160) = 411dp
可以看到屏幕的总 dp 宽度在不同的设备上是会变化的,但是我们在布局中填写的 dp 值却是固定不变的。

假设设计图总宽度为 375 dp,一个 View 在这个设计图上的尺寸是 50dp * 50dp。

验证设备 1

屏幕总宽度为 1080 px,根据公式求出 density,1080 / 375 = 2.88 (density)
这个 50dp 50dp 的 View,系统最后会将高宽都换算成 px,50dp 2.88 = 144 px (根据公式 dp * density = px)
144 / 1080 = 0.133,View 实际宽度与 屏幕总宽度 的比例和 View 在设计图中的比例一致 (50 / 375 = 0.133),所以完成了等比例缩放。

验证设备 2

屏幕总宽度为 1440 px,根据公式求出 density,1440 / 375 = 3.84 (density)
这个 50dp 50dp 的 View,系统最后会将高宽都换算成 px,50dp 3.84 = 192 px (根据公式 dp * density = px)
192 / 1440 = 0.133,View 实际宽度与 屏幕总宽度 的比例和 View 在设计图中的比例一致 (50 / 375 = 0.133),所以也完成了等比例缩放。

参考文章