Android:屏幕百分比适配

1,175 阅读1分钟

为什么dp的适配效果不理想?

以蓝湖上360dp宽的设计稿,60dp宽的控件为例

宽(px)density60dp控件(px)控件占比
设计稿720260*2=120px0.1666
小米910802.5260*2.52=151.2px0.14
Pixel XL14403.560*3.5=210px0.1458
荣耀畅玩57201.837560*1.8375=110.250.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 
}

优点

  1. 成本低,易实现
  2. 侵入性低,易回滚
  3. 全局适配

缺点

  1. 全局适配,当第三方库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>

优点

  1. 稳定,无性能损耗
  2. 自定义适配范围

缺点

  1. 侵入性高,维护难
  2. 机型覆盖有限,适配范围越广,相应包体大小越大

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"/>