问题背景
例如设计图宽度为375dp
,一个控件的宽度给的是200dp
,在设计图上占了200 / 375 = 53%
的宽度。
我们部分手机是这样的, 屏幕宽度为1080px
,density是3
,如果我们不做适配,直接在xml中填上200dp
,那么屏幕宽度占比就是 :(200*3)/ 1080 = 56%
,并没有做到等比例缩放。
在某些手机和设计图的分辨率差别更大的情况下,效果差别就更大。
抓住问题点:等比例缩放
要想做到等比例缩放,需要满足一个等式:
定义:控件宽度 = viewW ,屏幕宽度 = screenW;
200dp / 375dp = viewW / screenW
我们都以dp作为单位去设计xml,那么
screenW = 1080px / density
即:
200dp / 375dp = viewW / (1080px / density)
因为viewW控件宽度固定200dp
,屏幕宽度固定1080px
,想要等式成立,就必须修改density,这就是头条的适配方案。通过全局修改density的值,来做到等比例缩放。可以看到下面等式:
density = 1080 /375
上代码
在Activity的onCreate方法中,setContentView()方法之前调用,项目中可以写一个基类Activity,统一调用。
object ScreenMatchTool {
private var mOriginDensity = 0 // 原始density
private var mOriginScaleDensity = 0f // 原始文字缩放density
fun setCustomDensity(activity: Activity,application: Application) {
val applicationMetrics : DisplayMetrics = application.resources.displayMetrics
mOriginDensity = applicationMetrics.densityDpi
mOriginScaleDensity = applicationMetrics.scaledDensity
application.registerComponentCallbacks(object : ComponentCallbacks{
override fun onLowMemory() {
}
override fun onConfigurationChanged(newConfig: Configuration) {
// 用于监听系统修改文字大小
if (newConfig.fontScale > 0) {
mOriginScaleDensity = application.resources.displayMetrics.scaledDensity
}
}
})
/**
* 假如设计图是iPhone6s的尺寸为标准,分辨率:`750 x 1334 `,ppi:326 (网上可查)
* 那么density = 326 / 160 = 2, 实际宽度 = 750px / density = 375dp
*/
val targetDensity = applicationMetrics.scaledDensity / 375 // 修改后的density
val targetScaleDensity = targetDensity * (mOriginScaleDensity / mOriginDensity) // 修改后的文字缩放density
val targetDensityDpi = (targetDensity * 160).toInt() // 修改后的屏幕dpi
applicationMetrics.density = targetDensity
applicationMetrics.scaledDensity = targetScaleDensity
applicationMetrics.densityDpi = targetDensityDpi
val activityMetrics : DisplayMetrics = activity.resources.displayMetrics
activityMetrics.density = targetDensity
activityMetrics.scaledDensity = targetScaleDensity
activityMetrics.densityDpi = targetDensityDpi
}
}
做好适配之后,就可以直接将UI设计图中的dp值写进xml文件中,如果设计图给的是px(本人公司就是),需要做一个数学转换,将px转为dp,然后写入xml文件中。
转换方法:
- 需要知道设计图的标准,分辨率和屏幕ppi,或者和UI沟通是以什么机型为标准做的,分辨率和ppi网上均可查。
- density = ppi / 160;
- dp = px / density;
对于老项目来说,去用此方案适配,迁移量还是挺大的。如果是新项目完全可以使用,毕竟大公司方案,质量还是有保障的
网友评论