知识点
- 在为不同屏幕尺寸提供不同的布局时,注意 Android 3.2 之前和之后的不同限定符的使用
- 理解 Android 支持多种屏幕的主要两个方法。为不同屏幕尺寸提供不同的布局,为不同屏幕密度提供不同的位图对象。
如何支持多种屏幕
继续上一篇Android 支持多种屏幕第一篇
Android 支持多种屏幕的基础是它能够管理针对当前屏幕配置,以适当方式渲染应用的布局和位图对象。系统可处理大多数工作,通过适当的缩放布局以适应屏幕尺寸/密度和根据屏幕密度缩放位图可绘制对象,在每种屏幕配置中渲染应用。但,为了更好处理不同的屏幕配置,还应该:
为不同屏幕尺寸提供不同的布局
默认情况下,Android 会调整应用布局的大小以适应当前设备屏幕。但有时在一些设备上 UI 会变形,用户体验很差,需要针对不同的屏幕尺寸进行调整。例如,在较大的屏幕上,可能需要调整某些元素的位置和大小,以利用其它屏幕空间,或在较小的屏幕上,可能需要调整大小以使得所有内容容纳入屏幕。
可用提供尺寸特定资源的配置限定符包括 small、normal、large 和 xlarge。例如,超大屏幕的布局应使用 layout-xlarge/。
从 Android 3.2(API 级别 13)开始,以上尺寸组已弃用,我们应改为使用 sw<N>dp
配置限定符来定义布局资源可用的最小宽度。例如,如果多窗格平板电脑布局需要至少 600 dp 的屏幕宽度,应将其放在 layout-sw600dp/
中。
为不同屏幕密度提供不同的位图对象
默认情况下,Android 会缩放位图可绘制对象(.png
、.jpg
和 .gif
文件)和九宫格可绘制对象(.9.png
文件),使它们以适当的物理尺寸显示在每部设备上。例如,如果我们的应用只为基线中密度屏幕 (mdpi
) 提供位图对象,则在高密度屏幕上会增大位图,在低密度屏幕上会缩小位图。这种缩放可能在位图中造成伪影。为确保位图的最佳显示效果,应针对不同屏幕密度加入不同分辨率的替代版本。
可用于密度特定资源的配置限定符(在下面详述) 包括 ldpi
(低)、mdpi
(中)、hdpi
(高)、xhdpi
(超高)、xxhdpi
(超超高)和 xxxhdpi
(超超超高)。例如,高密度屏幕的位图应使用 drawable-hdpi/
。
注意:仅当要在 xxhdpi
设备上提供比正常位图大的启动器图标时才需要提供 mipmap-xxxhdpi
限定符,无需为所有应用的图像提供 xxxhdpi
资源。
将我们的所有启动器图标放在 res/mipmap-[density]/
文件夹中,而非 res/drawable-[density]/
文件夹中。无论安装应用的设备屏幕分辨率如何,Android 系统都会将资源保留在这些密度特定的文件夹中,例如 mipmap-xxxhdpi。此行为可让启动器应用为您的应用选择要显示在主 屏幕上的最佳分辨率图标。
Android 系统是如何确保任何给定资源在当前屏幕上都能保持尽可能最佳的显示效果?
在运行时,系统通过以下程序来确保任何给定资源在当前屏幕上都能保持尽可能最佳的显示效果:
系统使用适当的备用资源。根据当前屏幕的尺寸和密度,系统将使用应用中提供的任何尺寸和密度特定资源。例如,如果设备有高密度屏幕,并且应用请求可绘制对象资源,系统将查找与设备配置最匹配的可绘制对象资源目录。根据可用的其他备用资源,包含 hdpi 限定符(例如 drawable-hdpi/)的资源目录可能是最佳匹配项,因此系统将使用此目录中的可绘制对象资源。
如果没有匹配的资源,系统将使用默认资源,并按需要向上或向下扩展,以匹配当前的屏幕尺寸和密度。“默认”资源是指未标记配置限定符的资源。例如,
drawable/
中的资源是默认可绘制资源。系统假设默认资源设计用于基线屏幕尺寸和密度,即正常屏幕尺寸和中密度。 因此,系统对于高密度屏幕向上扩展默认密度资源,对于低密度屏幕向下扩展。
当系统在查找密度特定的资源但在密度特定目录中未找到时,不一定会使用默认资源。系统在缩放时可能改用其他密度特定资源提供更好的效果。
例如,查找低密度资源但该资源不可用时,系统会缩小资源的高密度版本,因为系统可轻松以 0.5
为系数将高密度资源缩小至低密度资源,与以 0.75
为系数缩小中密度资源相比,伪影更少。
在清单中显示声明应用支持那些屏幕尺寸
通过声明应用支持哪些屏幕尺寸,可确保只有其屏幕受支持的设备才能下载应用。
要声明应用支持的屏幕尺寸,在清单文件中包含 <supports-screens>
元素,这个我用的比较少。
使用配置限定符
配置限定符是可以附加到 Android 项目中资源目录的字符串,用于指定在其中设计资源的配置。
要使用的配置限定符:
- 在项目的
res/
目录中新建一个目录,并使用以下格式命名:<resources_name>-<qualifier>
<resources_name>
是标准资源名称(例如drawable
或layout
)。<qualifier>
是下表 1 中的配置限定符,用于指定要使用这些资源的屏幕配置(例如hdpi
或xlarge
)。也可以一次使用多个<qualifier>
— 只需使用短划线分隔每个限定符。
- 将适当的配置特定资源保存在此新目录下。这些资源 文件的名称必须与默认资源文件完全一样。
表 1. 可用于为不同屏幕配置提供特殊资源的配置限定符。
屏幕特性 | 限定符 | 说明 |
---|---|---|
- | ||
- | ||
- | ||
最小可用宽度 | sw<N>dp | 屏幕的基本尺寸,由可用屏幕区域的最小尺寸指定。示例:sw600dp |
可用屏幕宽度 | w<N>dp | 指定布局需要的最小宽度,而无需同时使用屏幕尺寸和方向限定符。 |
密度 | ldpi | 适用于低密度 (ldpi) 屏幕 (~120dpi) 的资源 |
- | mdpi | 适用于中密度 (mdpi) 屏幕 (~160dpi) 的资源,又叫基线密度 |
- | hdpi | 适用于高密度 (hdpi) 屏幕 (~240dpi) 的资源 |
- | xhdpi | 适用于超高密度 (xhdpi) 屏幕 (~320dpi) 的资源 |
- | xxhdpi | 适用于超超高密度 (xxhdpi) 屏幕 (~480dpi) 的资源 |
- | xxxhdpi | 适用于超超超高密度 (xxxhdpi) 屏幕 (~640dpi) 的资源,此限定符仅适用于启动器图标 |
- | nodpi | 适用于所有密度的资源,不管当前屏幕的密度如何,系统都不会缩放以此限定符标记的资源 |
… | … | … |
-
当 Android 系统在运行时选择使用哪些资源时,它会使用特定逻辑确定“最佳匹配”资源。也就是说,我们使用的限定符无需在所有情况下精确匹配当前屏幕配置,系统也可使用它们。
使用最小可用宽度(smallestWidth)
在版本低于 3.2 的 Android 设备上,我们通过通用的尺寸组(small
、normal
、large
、xlarge
)来设置多套布局。但这些组之间有的尺寸范围较大,如很多应用可能会针对此类别中的各种设备(例如 5 英寸和 7 英寸的设备)显示不同的布局。这就是 Android 3.2 版在引入其他限定符的同时引入“最小可用宽度”限定符的原因。
最小可用宽度(smallestWidth
),可以让我们通过指定某个最小宽度(以 dp 为单位)来定位屏幕。
例如,为标准 7 英寸平板电脑匹配双面板布局(其最小宽度为 600 dp),在手机(较小的屏幕上)匹配单面板布局。在创建单面板的同时使用 sw600dp
指明双面板布局仅适用于最小宽度为 600 dp 的屏幕,而不是使用 large
尺寸限定符。
使用布局别名
根据上文得知,我们需要提供以下文件:
res/layout/main.xml
: 单面板布局res/layout-large
: 多面板布局 (Android 3.2 之前)res/layout-sw600dp
: 多面板布局 (Android 3.2 之后)
而后两个文件是相同的。为避免文件出现重复(以及由此带来的维护问题),我们可以使用别名文件。
定义以下布局:
res/layout/main.xml
,单面板布局res/layout/main_twopanes.xml
,双面板布局
然后添加下面两个文件:
res/values-large/layout.xml:
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
res/values-sw600dp/layout.xml:
<resources>
<item name="main" type="layout">@layout/main_twopanes</item>
</resources>
应用支持多种屏幕的最佳做法
下面是针对不同屏幕配置正确缩放的技巧概览。
- 在 XML 布局文件中指定尺寸时使用
wrap_content
、match_parent
或dp
单位 ; - 不要在应用代码中使用硬编码的像素值;
- 为不同屏幕密度提供替代位图可绘制对象。
详细说明
1.对布局尺寸使用 wrap_content、match_parent 或 dp 单位。
为 XML 布局文件中的视图定义 android:layout_width
和 android:layout_height
时,使用 “wrap_content
“、 “match_parent
” 或 dp
单位可确保在当前设备屏幕上为 视图提供适当的尺寸。
2.不要在应用代码中使用硬编码的像素值。
由于性能的原因和简化代码的需要,Android 系统使用像素作为表示尺寸或坐标值的标准单位。这意味着, 视图的尺寸在代码中始终以像素表示,但始终基于当前的屏幕密度。
例如,如果 myView.getWidth()
返回 10,则表示视图在当前屏幕上为 10 像素宽,但在更高密度的屏幕上,返回的值可能是 15。如果 在应用代码中使用像素值来处理预先未针对当前屏幕密度缩放的位图,我们可能需要缩放代码中使用的像素值,以与未缩放的位图来源匹配。
3.使用尺寸和密度特定资源。
虽然系统会根据当前屏幕 配置扩展布局,但您在不同的屏幕尺寸上可能要调整 UI,以及提供 针对不同密度优化的可绘制对象。
总结
Android 系统对多种屏幕的设备都有一定的自适应能力。但,我们自己还需要做一些操作来更好处理不同的屏幕配置。为不同屏幕尺寸提供不同的布局,为不同屏幕密度提供不同的位图对象。在这个过程中也要注意配置限定符的使用。
参考文章