Android屏幕适配
图片显示先要分清像素、分辨率和密度。一张图由许多不同颜色的小方格组成,这样的小方格就叫像素,是构成图片的最小单位。像素的物理大小取决于显示设备上一个像素点的荧光点大小;图片文件只记录自己有多少像素、每个像素什么颜色,并不知道自己物理尺寸有多大。例如一张 480×800 的图在电脑显示器上明显比在手机上大,图本身没变,只是手机屏更精细、每个物理像素更小、密度更大。
一、像素、分辨率、密度
分辨率分「图片分辨率」与「物理显示分辨率」。它们都是水平像素点数与垂直像素点数的乘积,也就是像素总数。图片分辨率是文件记录的自身像素数;物理显示分辨率是屏水平与垂直能显示的像素数乘积。有人说分辨率越高图越清晰,这只针对物理尺寸相同的情况——一样的分辨率尺寸可能不同,单比分辨率没有可比性。
密度就是物理设备上单位尺寸里的像素数,密度越大图片显示就越清晰。
二、Android 的长度单位
-
px:像素,终端上的一个物理像素点。例如 480×800 的屏横向 480 个像素、纵向 800 个像素。 -
dip/dp:与物理像素无关,基于屏幕密度的抽象单位,称作设备独立像素,会随密度自动调整大小。 -
sp:比例像素,主要处理字体大小,可根据用户的字体大小首选项缩放。 -
in:英寸,标准长度单位。 -
mm:毫米,标准长度单位。 -
pt:磅,标准长度单位,1/72 英寸。
三、为什么要做屏幕适配
Android 终端的物理尺寸、分辨率类别众多。可能你为一种终端设计的 UI 符合要求,在另一类大小的物理终端上显示就完全不是你想要的。
Android 提供了一套标准,把屏幕分成三类。新建工程后会自动创建三个存放不同分辨率、不同密度 UI 的文件夹:
三个文件夹下的 UI 对应不同分辨率及密度:
| 资源目录 | 屏幕类型 | 分辨率 | 密度 | 尺寸 |
|---|---|---|---|---|
| drawable-hdpi | WVGA | 480×800 | 240 | 大 |
| drawable-mdpi | HVGA | 320×480 | 160 | 中 |
| drawable-ldpi | QVGA | 240×320 | 120 | 小 |
这三个文件夹只是告诉 Android:你设计的 UI 是针对哪种屏幕分辨率及密度。打开应用时,终端会自动匹配与文件夹里提供的 UI 相近分辨率及密度的图片。
假设终端是 WVGA(密度 240),程序会去抽 drawable-hdpi 下的图,然后用一个物理像素显示一个图片像素——因为你把图放在 hdpi,就是告诉系统 UI 针对 480×800、密度 240,于是不会放大或缩小。当图片密度与屏幕密度相同则不缩放;不同则缩放。
四、实验 1:只放一张 hdpi 图
针对 480×800 的屏设计一张图(分辨率 480×100),分别在不同物理分辨率终端下显示,看会不会不正常。原图:
布局文件:
假设这张图宽 480、高 100,放在 drawable-hdpi,就是告诉 Android 设计意图针对 480×800。它会在 480×800 终端上以一个物理像素显示一个图片像素。若拿到 240×320 终端上,如果系统不处理、仍一对一显示,终端必然显示不下,因为图片像素超过了物理像素个数。注意:这里只设计了一张图并只放在 hdpi,匹配时也就只能匹配这张图。
结果:
WVGA:对比原图,正好显示下,大小相同。
HVGA:对比原图,能够显示下,对图片进行了缩小。
QVGA:对比原图,能够显示下,对图片进行了缩小。
五、实验 2:只放一张 ldpi 图
针对 240×320 的屏设计一张图(分辨率 240×100),分别在不同终端显示。原图:
布局文件:
这张图专门为 240×320 设计,意图是撑满屏幕宽度,所以 wrap_content 就够,没有考虑其它屏。放在 drawable-ldpi,告诉系统针对 240×320、密度 120。在 240×320 上会一对一显示;若拿到 480×800 上系统不处理,图片像素小于物理像素,就会偏离「充满屏宽」的设计意图。
QVGA:对比原图,正好撑满屏宽。
HVGA:虽然设置成 wrap_content,Android 还是进行了放大。
WVGA:同上,也会放大。
总结:
-
只要对一种屏幕设计一套 UI,Android 总能通过放大或缩小来适应屏幕、保证设计意图,前提是布局里的单位是 dip。 -
虽然系统能保证设计意图,实际工作中最好还是多设计几套 UI。实验 2 里放大后的图明显模糊了许多。 -
如果只想设计一套 UI,最好针对大分辨率终端来设计:缩小比放大的清晰度更好。
六、实验 3:从文件路径读图
上面的图都从 drawable 获取,所以 Android 知道按什么密度处理(放大或缩小)。如果图是从 data/data 或 SD 卡获取,系统会默认把图片当作 160 的基准密度来处理。把实验二的图放入 data/data/cn.com/ 并设到 ImageView 上,本意是充满终端宽度,结果如何?
HVGA 屏下:
图片并没有如愿充满屏宽。原因是 Android 把图片密度当作 160 基准密度,而 HVGA 终端密度正好是 160,密度相同不会缩放,于是一对一显示:宽 240 像素的图当然无法充满宽 320 像素的屏。
希望从非 drawable 目录获取的图片也能智能缩放,就要告诉 Android 这张图按什么密度处理:
最终效果,HVGA 屏下:
结束:Android 中长度单位最好使用与物理像素无关的逻辑像素 dip,这样系统就能自动适应不同屏幕、保持设计意图。图片大小的转换是基于密度,与屏幕分辨率和尺寸大小无关。
一句话总结:布局用 dp/dip,图片按 hdpi/mdpi/ldpi 分桶;从文件读图时要自己设 inDensity 和 targetDensity,系统才会按密度缩放。
转载请注明来源:Android屏幕适配


















