Home Android Density屏幕适配
Post
Cancel

Android Density屏幕适配

简介

对于常见的项目中,UI都会以宽为基准来出图,这时就会以固定的屏幕宽度来定稿。但是安卓屏幕各异,密度各不相同,所以不能简单的直接使用dp来定义UI的样式。

DPI

在Android中,DPI表示屏幕像素密度。表示单位长度上对应的像素个数。在resource中有一个displayMetrics管理着对应的值。displayMetrics中有两个重要的参数

  • densityDpi,表示屏幕的dpi,dpi的基准为160,即160的dpi时1dp=1px,480的dpi时1dp=3px
  • density,即表示上面的比例关系,480dp时density为3。屏幕宽度=density*宽度总dp

屏幕适配

所以这时我们要使屏幕的宽度dp数固定,则density需要为屏幕总宽度/期望dp数,densityDpi再等于计算所得density乘160.大概就可以写出如下简单的适配方法了,这个更改会影响图片的加载放大比例,也会影响到第三方库中 UI相关dp的定义,但一般不会直接使用三方库的UI,所以影响不大

在Application中添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class App : Application() {

    init {
        registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks {
            override fun onActivityPreCreated(activity: Activity, savedInstanceState: Bundle?) {
                super.onActivityPreCreated(activity, savedInstanceState)
                // 在activity onCreate之前去更改,因为在setContentView时就会开始去生成view树了
                val appDisplayMetrics = resources.displayMetrics
                val activityDisplayMetrics = activity.resources.displayMetrics
                activityDisplayMetrics.density = appDisplayMetrics.density
                activityDisplayMetrics.densityDpi = appDisplayMetrics.densityDpi
            }
            
            //其实在onActivityCreated中也可以,这个方法使super.onCreate中调用的

            // ...
        })
    }

    override fun onCreate() {
        super.onCreate()
        val appDisplayMetrics = resources.displayMetrics
        // 这里举例期望的宽度为375dp
        val targetDensity = 1.0f * appDisplayMetrics.widthPixels / 375
        val targetDensityDpi = (targetDensity * 160).toInt()
        // 更改app中默认的参数
        appDisplayMetrics.density = targetDensity
        appDisplayMetrics.densityDpi = targetDensityDpi
    }

    companion object {
        var activity: Activity? = null
    }
}

参考

This post is licensed under CC BY 4.0 by the author.