1.简介
在Android开发中,由于Android碎片化严重,屏幕分辨率千奇百怪,而想要在各种分辨率的设备上显示基本一致的效果,适配成本越来越高。虽然Android官方提供了dp单位来适配,但其在各种奇怪分辨率下表现却不尽如人意,因此下面探索一种简单且低侵入的适配方式。
2.了解一下之间的关系
先来了解下px,dp,dpi,density之间的关系
1.px(pixel 像素):就是屏幕上实际的像素点单位,一般HVGA代表320x480像素。
2.dp / dip:设备独立像素,android layout经常使用的尺寸单位,与设备屏幕有关,dp是虚拟像素,在不同的像素密度的设备上会自动适配。即与像素密度无关。而dpi是根据屏幕真实的分辨率和尺寸来计算的,每个设备都可能不一样的。
系统屏幕密度
ldpi文件夹下对应的密度为120dpi,对应的分辨率为240 * 320
mdpi文件夹下对应的密度为160dpi,对应的分辨率为320 * 480
hdpi文件夹下对应的密度为240dpi,对应的分辨率为480 * 800
xhdpi文件夹下对应的密度为320dpi,对应的分辨率为720 * 1280
xxhdpi文件夹下对应的密度为480dpi,对应的分辨率为1080 * 1920
android系统将密度为160dpi的屏幕作为标准对于mdpi文件夹,在此屏幕的手机上1dp=1px。从上面系统屏幕密度可以得出各个密度值之间的换算;
mdpi中1dp=1px,
hdpi中1dp=1.5px
xhdpi中1dp=2px
xxhpi中1dp=3px
3.density:指的是1dp占当前屏幕的像素。 density = DPI / 160
2.1.屏幕尺寸、分辨率、像素密度三者关系
通常情况下,一部手机的分辨率是宽x高,屏幕大小是以寸为单位,那么三者的关系是:
举个例子:屏幕分辨率为:1920*1080,屏幕尺寸为5吋的话,那么dpi为440。
主要讲讲现在最主流的两种屏幕适配方案,今日头条适配方案 和 smallestWidth 限定符适配方案
建议大家不清楚这两个方案的先看看这两篇文章,才清楚我在讲什么,后面我要讲解它们的原理,以及验证这两种方案是否真的可行,最后对他们进行深入对比,对于他们的一些缺点给予对应的解决方案,绝对干货。
适配方案:
1.今日头条适配方案
原理:适配方案的核心原理在于,根据以下公式算出 density
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
density 的意思就是 1 dp 占当前设备多少像素
为什么要算出density,这和屏幕适配有什么关系呢?
我们都知道,在我们布局文件中填写的是什么单位,最终都会被转化为px,所以我们常用px转化dp的公式。
公式:dp = px / density
density = dpi / 160
density 在每个设备上都是固定的,屏幕的总(px)宽度 / density = 屏幕的总(dp)宽度
例如:
设备 1,屏幕宽度为 1080px,480DPI,屏幕总 dp 宽度为 1080 / (480 / 160) = 360dp
设备 2,屏幕宽度为 1440px,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 在任何分辨率的屏幕上,与屏幕的比例都是相同的
这时我们该怎么做呢?改变每个 View 的 dp 值?不现实,在每个设备上都要通过代码动态计算 View 的 dp 值,工作量太大
如果每个 View 的 dp 值是固定不变的,那我们只要保证每个设备的屏幕总 dp 宽度不变,就能保证每个 View 在所有分辨率的屏幕上与屏幕的比例都保持不变,从而完成等比例适配,并且这个屏幕总 dp 宽度如果还能保证和设计图的宽度一致的话,那我们在布局时就可以直接按照设计图上的尺寸填写 dp 值
屏幕的总 px 宽度 / density = 屏幕的总 dp 宽度
在这个公式中我们要保证 屏幕的总 dp 宽度 和 设计图总宽度 一致,并且在所有分辨率的屏幕上都保持不变,我们需要怎么做呢?屏幕的总 px 宽度 每个设备都不一致,这个值是肯定会变化的,这时今日头条的公式就派上用场了
当前设备屏幕总宽度(单位为像素)/ 设计图总宽度(单位为 dp) = density
这个公式就是把上面公式中的 屏幕的总 dp 宽度 换成 设计图总宽度,原理都是一样的,只要 density 根据不同的设备进行实时计算并作出改变,就能保证 设计图总宽度 不变,也就完成了适配
验证设备 1
屏幕总宽度为 1080 px,根据今日头条的的公式求出 density 1080(屏幕宽度px) / 375(设计图总宽度dp) = 2.88 (density)
如果一个 50dp * 50dp 的 View,系统最后会将高宽都换算成 px,50dp * 2.88 = 144 px (根据公式 dp * density = px)
View 实际宽度与 屏幕总宽度 的比例 :144 / 1080 = 0.133
View 和设计图中的比例: 50 / 375 = 0.133 所以完成了等比例缩放
某些设备总宽度为 1080 px,但是 DPI 可能不同,是否会对今日头条适配方案产生影响?其实这个方案根本没有根据 DPI 求出 density,是根据自己的公式求出的 density,所以这对今日头条的方案没有影响
验证设备 2
屏幕总宽度为 1440 px,根据今日头条的的公式求出 density,1440(屏幕宽度px) / 375(设计图总宽度dp) = 3.84 (density)
如果一个 50dp * 50dp 的 View,系统最后会将高宽都换算成 px,50dp * 3.84 = 192 px (根据公式 dp * density = px)
View 实际宽度与 屏幕总宽度 的比例 :192 / 1440 = 0.133
View 和设计图中的比例: 50 / 375 = 0.133 所以完成了等比例缩放
两个不同分辨率的设备都完成了等比例缩放,证明今日头条屏幕适配方案在不同分辨率的设备上都是有效的,如果大家还心存疑虑,可以再试试其他分辨率的设备,其实到最后得出的比例不会有任何偏差, 都是 0.133
地址:https://github.com/JessYanCoding/AndroidAutoSize
使用:
添加:implementation 'me.jessyan:autosize:1.1.2'
在我们在清单文件中配置
<manifest>
<application>
<meta-data
android:name="design_width_in_dp"
android:value="1080"/>
<meta-data
android:name="design_height_in_dp"
android:value="1920"/>
</application>
</manifest>
2.SmallestWidth限定符适配方案