1. 概念理解
像素(px/pixel)
屏幕上的点,是数码设备最小的独立显示单位,例如分辨率 1920×1080 就表示屏幕中共有 1920 * 1080 个像素点。
在 Android 开发中,不建议直接使用 px,而是建议使用 dp 来定义视图尺寸,以适配不同屏幕密度。
分辨率(Resolution)
指屏幕纵向和横向的像素数量。例如分辨率为 1920×1080,表示屏幕纵向有 1920 个像素点,横向有 1080 个像素点。
英寸(in/inch)
用于表示屏幕的对角线物理长度。1 英寸 = 2.54 厘米。常用于描述设备屏幕大小(例如手机是 6.1 英寸,显示器是 27 英寸等)。
PPI(Pixels Per Inch)
表示每英寸包含的像素点数量,衡量的是屏幕的实际显示精度和清晰度。PPI =纵向像素平方+横向像素平方之和开根(初中勾股定理,求直角三角形斜边)再除以屏幕英寸值。例如一块 1920×1080 分辨率、5 英寸的手机屏幕,PPI ≈ √(1920² + 1080²) / 5 ≈ 441。
PPI 是一个物理值,不同于 Android 中使用的 DPI(抽象密度),后者是为屏幕适配而设定的标准值。
DPI(Dots Per Inch) / 抽象密度(Android 中的 densityDpi)
原本是打印行业用来衡量打印精度的单位,但在 Android 中,DPI 是一种抽象的屏幕密度等级,用于适配不同屏幕尺寸和分辨率。
Google 在 Android 系统中为不同屏幕设备“设定”的一种虚拟屏幕密度(density),用于统一界面元素在不同设备上的显示效果。
DPI并不一定等于设备的真实 PPI(仅值相近),而是一个归一化后的标准密度等级,这样开发者就不需要针对每一个屏幕精确适配,而是根据分类来适配就可以了。比如:mdpi → 160;hdpi → 240;xxhdpi → 480等。
可通过代码获取:
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
int densityDpi = metrics.densityDpi; // 例如 480(即 xxhdpi)
密度(density)
Android 的屏幕密度是指相对密度,density = DPI/160。其中 160 DPI 被 Android 定为基准密度(mdpi),即 density = 1。系统会根据 density 自动缩放 dp 单位。
可通过代码获取:
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float density = metrics.density; // 例如 3.0
dp(device independent pixels/与密度无关的像素)
在屏幕密度为 160dpi(mdpi)时,1dp = 1px。在其他密度下,系统会根据 density 自动换算成合适的像素数。开发中推荐使用 dp 来定义视图尺寸,从而适配各种屏幕。dp = px / density 或 px = dp × density
sp(scale-independent pixel / 可缩放像素)
与 dp 类似,它用于定义文字大小。sp 会根据用户设置的字体大小偏好进行缩放。
pt(point / 磅)
在印刷单位中,1pt = 1/72 英寸。Android 中也支持 pt 作为单位,但使用较少。
2. Android 抽象 DPI 与 density 对照表
抽象密度名称 |
DPI抽象范围 | density 值 | 常见情况下可能的分辨率(具体要结合英寸) |
低密度(ldpi) |
0~120dpi |
0.75 / 1dp=0.75px |
320*240 |
中密度(mdpi) |
120~160dpi |
1 |
480*320 |
高密度(hdpi) |
160~240dpi |
1.5 |
800*480 |
超高密度(xhdpi) |
240~320dpi |
2 |
1280*720 |
extra high(xxhdpi) |
320~480dpi |
3 |
1920*1080 |
extra extra high (xxxhdpi) |
480~640dpi |
4 |
2560 * 1440(2K分辨率) |
extra extra extra high(xxxxhdpi) |
640~960dpi |
6 |
3840 * 2160(4K分辨率)(4K电影其影片分辨率4096×2160,而电视、手机领域,由于过去屏幕16:9为主流比例,因此4K指的是3840×2160的物理分辨率) |
3. dp转换px
如上述提到,px = dp × density 即px = dp × (dpi / 160 ),其中dpi可以是120、160、240、320,等。因此,当一个100dp的Button显示在一个315ppi的屏幕上时,其实际宽度是100 * ( 320 / 160 ) = 200px。为了证明,你可以在XML布局中定义100dp的Button,而在代码中获取Button对象使用对象的getWidth()方法获得其以像素数为单位的宽度看看是否为200px。
在实际开发中,若需要进行dp和px的转义,可以使用以下代码:
public static int dp2px(Context context, float dp) {
// +0.5f是为了四舍五入
return (int) (TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics()) + 0.5f);
}