Android 屏幕尺寸与单位换算全解析:dp、sp、px 谁才是真正的主角?

15 阅读5分钟

在 Android 开发中,如果你还在用 px 来布局,那真得是“像素级冒险”!
记住三句话就能避坑:

  • 布局用 dp —— 保证在不同分辨率下视觉一致;
  • 字体用 sp —— 自动跟随系统字体大小调整,提升可访问性;
  • 像素密度 dpi —— 决定 dp 与 px 的换算关系,是屏幕适配的核心指标。

一、关键名词解析

px(Pixels)

屏幕的最小显示单位。
同样是 100px,在小屏高密度手机上看起来会比大屏低密度手机小很多。
👉 不建议直接在布局中使用


分辨率(Resolution)

屏幕在水平和垂直方向上的总像素数,例如 2720x1260
它仅描述像素数量,不代表物理显示大小。


dpi(dots per inch, 像素密度)

每英寸长度上排列的像素点数量,决定显示细腻度。
Android 将设备按 dpi 划分为密度桶(Density Bucket),常见有:

等级标准 dpidp 转 px 换算比例
ldpi~1200.75
mdpi~1601.0
hdpi~2401.5
xhdpi~3202.0
xxhdpi~4803.0
xxxhdpi~6404.0

dp(device-independent pixel)

开发中最常用的长度单位,旨在让同一数值在不同 dpi 的设备上呈现接近相同的物理尺寸。

公式:

px = dp * (dpi / 160)

例如:在 320dpi 的屏幕上,1dp = 2px。


sp(scale-independent pixel)

专用于字体大小,类似 dp,但会额外受到用户系统字体设置的影响。
所有文字大小都应使用 sp


二、计算规则与实例(小米 / 华为机型)

我们选取两款主流机型作为实例:小米 14(小屏旗舰)和华为 Mate 60 Pro(大屏旗舰),通过对比计算,更直观地理解单位换算逻辑。


实例 1:小米 14(小屏旗舰)

已知参数(来自小米官方数据):

  • 屏幕尺寸:6.36 英寸
  • 分辨率:2670 × 1200 像素
  • 官方标称 PPI(像素密度) :460

验证对角线像素首先通过分辨率计算屏幕对角线的像素总数,公式为勾股定理:

对角线像素 = √(横向像素² + 纵向像素²)
计算过程:√(2670² + 1200²) = √(7,128,900 + 1,440,000) = √8,568,9002927 px

计算 dpi (像素密度) 用对角线像素除以屏幕实际物理尺寸(英寸):

dpi = 对角线像素 / 屏幕尺寸 = 2927 px / 6.36 in ≈ 460 dpi

这与官方标称的 460 PPI 完全一致。根据 Android 密度桶划分标准,460dpi 属于 xxhdpi 密度桶(范围 320-479dpi)。

dp 与 px 的换算公式:

px = dp * (dpi / 160)

假设设置一个 120dp 的按钮宽度:

在小米 14 上:120 * (460 / 160) ≈ 345 px

这意味着在小米 14 的屏幕上,120dp 会被渲染为约 345 个物理像素点。


实例 2:华为 Mate 60 Pro(大屏旗舰)

已知参数(来自华为官方数据):

  • 屏幕尺寸:6.82 英寸
  • 分辨率:2720 × 1260 像素

计算对角线像素:

对角线像素 = √(2720² + 1260²) = √(7,398,400 + 1,587,600) = √8,986,0002998 px

计算 dpi (像素密度):

dpi = 2998 px / 6.82 in ≈ 439 dpi

439dpi 同样属于 xxhdpi 密度桶,与小米 14 处于同一区间,但数值略低。

dp 与 px 的换算同样以 120dp 的按钮宽度为例:

在华为 Mate 60 Pro 上:120 * (439 / 160) ≈ 329 px

虽然换算出的 px 数值比小米 14 小,但由于华为 Mate 60 Pro 屏幕尺寸更大,120dp 对应的物理宽度与小米 14 上的 120dp 几乎一致(约 7.5 毫米),这正是 dp 作为 “设备独立像素” 的核心价值。

对比总结

  • 小米 14(460dpi) → 345px
  • 华为 Mate 60 Pro(439dpi) → 329px

尽管像素数不同,但物理尺寸几乎相同,确保了跨设备一致性。


三、开发最佳实践

XML 布局

<Button
    android:layout_width="120dp"
    android:layout_height="48dp"
    android:layout_marginTop="20dp"
    android:text="点击按钮"
    android:textSize="16sp" />

Kotlin 工具类

object DisplayUtils {
    fun dpToPx(context: Context, dp: Float): Int {
        val metrics = context.resources.displayMetrics
        return (dp * metrics.density + 0.5f).toInt()
    }

    fun spToPx(context: Context, sp: Float): Int {
        val metrics = context.resources.displayMetrics
        return (sp * metrics.scaledDensity + 0.5f).toInt()
    }

    fun getDeviceDpi(context: Context): Int {
        return context.resources.displayMetrics.densityDpi
    }
}

四、屏幕适配方案

方案 1:官方推荐 — smallestWidth 限定符

自动生成不同屏幕下的 dp 文件,适合新项目或使用 smallestWidth 插件

values-sw360dp/
values-sw480dp/
values-sw600dp/

方案 2:手动适配(老项目)

通过比例计算控件实际 px 值,保留老布局结构,常用于渐进式重构。

val epicDensity = designPpi / 160
val epicBaseWidth = designWidthPx / epicDensity
val epic = controlWidthPx / epicDensity
val actualPx = (epic * context.resources.displayMetrics.widthPixels / epicBaseWidth)

五、实用建议

  1. 布局尺寸 一律用 dp
  2. 文字大小 一律用 sp
  3. 图片资源 提供多分辨率版本
  4. 避免直接使用 px,除非特殊绘制或 Canvas 逻辑

总结

dp 让布局更通用,sp 让文字更友好,dpi 决定显示更精准。

掌握 dp、sp 和 dpi 的关系,你的 UI 在任何 Android 设备上都能保持“颜值稳定”。