dp, sp, px 与 Android 界面布局自适应

文章目录

    之前写 Android 平板 App,由于没有正经写过 Android 界面布局,为了图省事,
    直接用 px 像素做的布局,及字号大小设置。

    好在平板是我们指定的型号,屏幕尺寸,及像素。但是自从发货到客户手中之后,
    我就非常担心,一旦这款平板停产,换个更高分辨率的平板怎么办?

    为了消除焦虑,我了解了一下 Android 布局的基础。

    总结起来一句话:

    字号用 sp,宽高用 dp。

    问题简化

    • 图片宽度用什么单位? dp
    • 字号用什么单位?sp
    • dp 是什么?
    • dp 是怎么换算为 px 的?

    dp 是怎么换算为 px 的

    android 中,dp 在渲染前,都会被转换成 px。

    px = density * dp
    

    density 密度

    density 即,密度的意思。

    Android kotlin 获取 density (float 类型):

    val density = resources.displayMetrics.density
    

    例如,在我当前使用的华为平板中,density 值为 1.75; 小米手机为 2.75。

    获取 Android 设备的屏幕信息,即宽度对应的 dp

    比如在 main activity 中定义一个获取屏幕信息的 kotlin 函数:

    private fun getScreenInfo(context: Context) {
    	val displayMetrics = resources.displayMetrics
    
    	val screenWidthInPx = displayMetrics.widthPixels
    	val density = displayMetrics.density
    	val dpi = displayMetrics.densityDpi
    	val screenWidthInDp = (screenWidthInPx / density).toInt()
    
    	// 台电平板:screenWidthInPx: 1920, density: 1.75, screenWidthInDp: 1097, dpi: 280
        // 华为平板:screenWidthInPx: 2000, density: 2.0, screenWidthInDp: 1000, dpi: 320
    	println("screenWidthInPx: $screenWidthInPx, density: $density, screenWidthInDp: $screenWidthInDp, dpi: $dpi")
    }
    

    然后在 onCreate 中调用:

    getScreenInfo(this)
    

    根据输出的 screenWidthInDp: 1097。

    可以将蓝湖/codesign 这类设计工具中的宽度变更为 1097,以自动转换界面元素的大小。

    手里两个平板,一个华为,一个台电,上面4个参数都完全一样。

    而我的小米手机在竖屏/横屏不同状态下,返回的 screenWidthInDp 是不一样的。

    screenWidthInPx: 1080, density: 2.75, screenWidthInDp: 392, dpi: 440
    screenWidthInPx: 2270, density: 2.75, screenWidthInDp: 825, dpi: 440
    

    看起来手机上的 screenWidthInDp 比平板的要小。所以如果要兼容手机,布局上还是要灵活一点。

    DPI 与 PPI

    • DPI(Dots Per Inch,每英寸点数, 一英寸等于2.54厘米)
    • PPI(Pixels Per Inch,每英寸像素密度)

    PPI(Pixels Per Inch)则是一个描述屏幕像素密度的度量单位。
    它指的是在每英寸线性距离上的像素数量。
    PPI 的概念主要应用于显示设备,用于表示屏幕上每英寸的像素数量。
    PPI 值越高,屏幕显示的图像就越细腻和清晰。

    不同 dp 宽度屏幕的兼容性/自适应问题

    虽然很多 android 平板,看上去是都是 10.1 寸屏,但是实际上有的屏幕像素密度很低,比如 Android 工控屏。
    这时,其 dp 为单位的宽度,就比正常的平板,要大一些。就会导致布局看起来跟预想的不一样。

    还是需要一些布局的基本原则的:

    • 考虑清楚那部分应该是居中的
    • 不要使用上下左右边距,即 margin,来布局边界元素。尽量使用居中排版
    • 考虑 max,min 各种尺寸的屏幕,其 dp 大概有多大。做类似于 web 那样的布局方案

    英寸与英尺

    • 一英寸等于 2.54 厘米
    • 一英尺等于 30.48 厘米

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式