2. Android屏幕基础
做Android适配,第一步不是写布局,而是把“屏幕”这件事拆开看清楚。很多适配问题之所以反复出现,根源在于把物理尺寸、像素数量、像素密度和逻辑单位混为一谈。本节把屏幕尺寸、分辨率、像素密度、dp、sp、px这几个概念一次讲透,并给出可直接用于计算的换算关系。
一、四个物理概念:尺寸、分辨率、像素密度、px
屏幕尺寸(Screen Size)指屏幕对角线的物理长度,单位是英寸(inch)。例如常说的“6.1英寸手机”,指的是对角线长度,而不是宽或高。它描述的是“屏幕有多大”,与像素无关。
分辨率(Resolution)指屏幕上实际存在的物理像素总数,通常写成“宽×高”,如 1080×2400。它描述的是“屏幕上有多少个像素点”。分辨率越高,画面能承载的细节越多,但不代表屏幕一定更大。
像素密度(DPI / PPI)指每英寸包含的像素数。Android中常用 dpi(dots per inch)表示,计算公式为:对角线像素数 ÷ 对角线英寸数。例如 1080×2400、6.1英寸的屏幕,对角线像素约为 √(1080²+2400²)≈2632,2632÷6.1≈431,接近 440dpi 档位。
px(像素)是屏幕上的最小显示单位,是物理像素。在代码中直接写 px 意味着“我就要这么多物理像素”,它不会随设备密度自动缩放,因此在不同手机上视觉大小差异极大,通常不作为布局单位使用。
二、逻辑单位:dp 与 sp 的由来
如果所有设备都用 px 布局,同一份代码在低密度屏上会显得很大,在高密度屏上会显得很小。Android 的解决方案是引入与密度无关的逻辑单位。
dp(density-independent pixel,密度无关像素)用于描述长度、间距、控件尺寸。它以 160dpi 为基准:在 160dpi 的设备上,1dp = 1px。在其他密度上,系统按比例放大 px 数量,从而保证物理视觉大小基本一致。
sp(scale-independent pixel,缩放无关像素)用于描述字体大小。它和 dp 类似,但会额外乘以用户的“字体大小”偏好系数。用户把系统字体调大时,sp 会跟着变大,而 dp 不会。因此正文文字必须用 sp,才能尊重无障碍设置。
三、换算关系与密度限定符
核心换算公式只有一个:px = dp × (dpi ÷ 160),其中 dpi÷160 称为密度倍数(density)。反过来:dp = px ÷ (dpi ÷ 160)。Android 把常见密度归入固定档位,并对应不同资源目录。
| 密度档位 | dpi | 密度倍数 | 资源目录 | 1dp 对应 px |
|---|---|---|---|---|
| ldpi | 120 | 0.75 | drawable-ldpi | 0.75px |
| mdpi | 160 | 1.0 | drawable-mdpi | 1px |
| hdpi | 240 | 1.5 | drawable-hdpi | 1.5px |
| xhdpi | 320 | 2.0 | drawable-xhdpi | 2px |
| xxhdpi | 480 | 3.0 | drawable-xxhdpi | 3px |
| xxxhdpi | 640 | 4.0 | drawable-xxxhdpi | 4px |
在代码中获取密度并换算:
// 获取当前屏幕密度
float density = getResources().getDisplayMetrics().density;
float scaledDensity = getResources().getDisplayMetrics().scaledDensity;
// dp 转 px
int px = (int) (dpValue * density + 0.5f);
// px 转 dp
float dp = pxValue / density;
// sp 转 px(字体)
int fontPx = (int) (spValue * scaledDensity + 0.5f);
注意:density 是 dp 的倍数,scaledDensity 是 sp 的倍数,两者在用户未调整字体时相等,调整字体后 scaledDensity 会大于 density。混用这两个值,是字体适配出错的常见原因。
四、典型场景:同一张图在不同密度下的表现
假设设计稿基于 360dp 宽、xxhdpi(480dpi,倍数3)绘制,标注一个按钮宽 120dp、高 48dp、文字 16sp。在 xxhdpi 设备上,按钮实际占 360px×144px;在 mdpi 设备上,只占 120px×48px。虽然像素数不同,但物理视觉大小接近,这就是 dp 的价值。
如果误把 120dp 写成 120px,那么在 xxhdpi 上按钮只有 40dp 宽,视觉上明显偏小;在 mdpi 上又刚好合适。同一份代码在不同设备上“时大时小”,正是 px 布局的典型症状。
五、常见误区与复盘
- 误区一:把分辨率当成屏幕大小。1080×2400 只说明像素数量,6.1 英寸和 6.7 英寸都可能是这个分辨率,像素密度不同,视觉细腻度也不同。
- 误区二:布局里直接写 px。px 不随密度缩放,会导致高密度设备上控件偏小、低密度设备上偏大。除极少数需要精确物理像素的场景(如1px分割线),布局应使用 dp。
- 误区三:字体用 dp。dp 不响应用户字体设置,用户调大字体后文字不变,属于无障碍缺陷。字体必须用 sp。
- 误区四:sp 换算用 density。sp 应使用 scaledDensity,否则用户调整字体后换算结果错误。
- 误区五:只提供一套切图。应至少覆盖 mdpi 到 xxxhdpi 的主流档位,或使用矢量图与自适应资源,避免高密度设备拉伸模糊。
把尺寸、分辨率、像素密度、dp、sp、px 的关系理清后,后续的布局适配、图片适配、旋转适配才有统一的度量基础。记住一句话:物理世界看英寸和 dpi,代码世界看 dp 和 sp,px 只在需要精确物理像素时出现。