为什么dp的适配效果不理想?
以蓝湖上360dp宽的设计稿,60dp宽的控件为例
| 宽(px) | density | 60dp控件(px) | 控件占比 | |
|---|---|---|---|---|
| 设计稿 | 720 | 2 | 60*2=120px | 0.1666 |
| 小米9 | 1080 | 2.52 | 60*2.52=151.2px | 0.14 |
| Pixel XL | 1440 | 3.5 | 60*3.5=210px | 0.1458 |
| 荣耀畅玩5 | 720 | 1.8375 | 60*1.8375=110.25 | 0.153125 |
屏幕适配就是使得控件在实际屏幕中的大小占比与在设计稿中的一致
今日头条适配方案
原理:px = dp * density
假定设计稿宽为360dp,以此为基准,要想达到适配效果,就要使所有设备的宽dp值都为360dp。设备的宽px值是物理固定的,此时修改density便能达到目的
fun customerDensity(app: Application) {
val displayMetrics = app.resources.displayMetrics
// 获取屏幕宽
val screenWidth = displayMetrics.widthPixels // density = px / dp
val targetDensity = screenWidth / 360f
val targetDensityDpi = (160 * targetDensity).toInt()
displayMetrics.density = targetDensity
displayMetrics.densityDpi = targetDensityDpi
}
优点
- 成本低,易实现
- 侵入性低,易回滚
- 全局适配
缺点
- 全局适配,当第三方库UI设计规则出入太大,实际适配效果天差地别
smallestWidth限定符适配
原理
系统会根据当前设备屏幕的最小宽度 (smallestWidth) 去匹配对应的 values-swdp 文件夹下dimens.xml,如未找到,则会去寻找小于或等于sw 的values-swdp 文件夹
以360dp的设计稿为例
创建 values-sw360dp下的dimens.xml,如下:
<resources>
<dimen name="dp_1">1dp</dimen>
<dimen name="dp_2">2dp</dimen>
...
<dimen name="dp_359">359dp</dimen>
<dimen name="dp_360">360dp</dimen>
</resources>
以宽360dp为基准,则values-sw380dp下dimens.xml单位值为380/360=1.05555
<resources>
<dimen name="dp_1">1.05555dp</dimen>
<dimen name="dp_2">2.11111dp</dimen>
...
<dimen name="dp_359">378.944dp</dimen>
<dimen name="dp_360">380dp</dimen>
</resources>
优点
- 稳定,无性能损耗
- 自定义适配范围
缺点
- 侵入性高,维护难
- 机型覆盖有限,适配范围越广,相应包体大小越大
ConstraintLayout百分比宽高
<View
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintHeight_percent="0.1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>