备用资源

备用资源是面向特定设备或运行时配置的那些资源,例如当前语言、特定屏幕大小或像素密度。 如果 Android 可以匹配比默认资源更特定于特定设备或配置的资源,则将改用该资源。 如果找不到与当前配置匹配的备用资源,则会加载默认资源。 下面的“资源位置”部分将更详细地介绍 Android 如何确定应用程序将使用的资源

备用资源将根据资源类型组织为 Resources 文件夹中的子目录,就像默认资源一样。 备用资源子目录的名称采用以下形式:ResourceType-限定符

限定符是用于标识特定设备配置的名称。 名称中可能有多个限定符,每个限定符都用短划线分隔。 例如,下面的屏幕截图显示了一个简单的项目,其中包含各种配置(例如区域设置、屏幕密度、屏幕大小和方向)的备用资源:

将限定符添加到资源类型时,适用以下规则:

  1. 可能有多个限定符,每个限定符用短划线分隔。

  2. 限定符可能只指定一次。

  3. 限定符必须按在下表中显示的顺序排列。

下面列出了可能的限定符以供参考:

  • MCC 和 MNC – 即移动国家/地区代码 (MCC) 和可选的移动网络代码 (MNC)。 SIM 卡将提供 MCC,而设备连接到的网络将提供 MNC。 虽然可以使用移动国家/地区代码来确定面向的区域设置,但建议的方法是使用下面指定的语言限定符。 例如,若要将资源设为面向德国,限定符将为 mcc262。 若要将资源设为面向美国的 T-Mobile,限定符为 mcc310-mnc026。 有关移动国家/地区代码和移动网络代码的完整列表,请参阅 http://mcc-mnc.com/

  • 语言 – 双字母 ISO 639-1 语言代码,且可选择后跟双字母 ISO-3166-alpha-2 区域代码。 如果同时提供这两个限定符,则它们由 -r 分隔。 例如,若要面向法语区域设置,则使用 fr 限定符。 若要面向法国-加拿大区域设置,将使用 fr-rCA。 有关语言代码和区域代码的完整列表,请参阅表示语言名称的代码国家/地区名称和码位元素

  • 最小宽度 – 指定应用程序要用于执行的最小屏幕宽度。 为不同屏幕创建资源中对此进行了更详细的介绍。 在 API 级别 13(Android 3.2)及更级别本中可用。 例如,限定符 sw320dp 用于定位高度和宽度至少为 320dp 的设备。

  • 可用宽度 – wNdp 格式的屏幕最小宽度,其中 N 是以密度无关像素为单位的宽度。 当用户旋转设备时,此值可能会改变。 为不同屏幕创建资源中对此进行了更详细的介绍。 在 API 级别 13(Android 3.2)及更级别本中可用。 示例:限定符 w720dp 用于定位宽度至少为 720dp 的设备。

  • 可用高度 – hNdp 格式的屏幕最小高度,其中 N 是以 dp 为单位的高度。 当用户旋转设备时,此值可能会改变。 为不同屏幕创建资源中对此进行了更详细的介绍。 在 API 级别 13(Android 3.2)及更级别本中可用。 例如,限定符 h720dp 用于定位高度至少为 720dp 的设备

  • 屏幕大小 – 此限定符是这些资源所针对的屏幕大小的通用化。 为不同屏幕创建资源中对此进行了更详细的介绍。 可能值为 smallnormallargexlarge。 已在 API 级别 9(Android 2.3/Android 2.3.1/Android 2.3.2)中添加

  • 屏幕纵横 – 该限定符将基于纵横比,而不是屏幕方向。 长屏将会更宽。 已在 API 级别 4 (Android 1.6) 中添加。 可能的值为 long 和 notlong。

  • 屏幕方向 – 纵向或横向的屏幕方向。 这可能在应用程序的生存期内发生变化。 可能值为 portland

  • 基座模式 – 指定设备是采用车载基座还是桌面基座。 已在 API 级别 8 (Android 2.2.x) 中添加。 可能值为 cardesk

  • 夜间模式 – 应用程序是在夜间还是白天运行。 这可能会在应用程序的生存期内发生改变,旨在让开发人员有机会在夜间使用较暗版本的界面。 已在 API 级别 8 (Android 2.2.x) 中添加。 可能值为 nightnotnight

  • 屏幕像素密度 (dpi) – 物理屏幕上给定区域中的像素数。 通常以每英寸点数 (dpi) 表示。 可能的值为:

    • ldpi – 低密度屏幕。

    • mdpi – 中等密度屏幕

    • hdpi – 高密度屏幕

    • xhdpi – 超过高密度屏幕

    • nodpi – 不可缩放的资源

    • tvdpi – 在 API 级别 13(Android 3.2)中引入,针对 mdpi 和 hdpi 之间的屏幕。

  • 触摸屏类型 – 指定设备可能具有的触摸屏类型。 可能的值为 notouch(无触摸屏)、stylus(适用于手写笔的电阻式触摸屏)和 finger(触摸屏)。

  • 键盘可用性 – 指定可用的键盘类型。 这可能会在应用程序的生存期内发生改变,例如当用户打开硬件键盘时。 可能的值为:

    • keysexposed – 设备具有可用的键盘。 如果没有启用软件键盘,则仅当打开硬件键盘时才会使用该值。

    • keyshidden – 设备确实具有硬件键盘,但它处于隐藏状态,并且未启用软件键盘。

    • keyssoft – 设备启用了软件键盘。

  • 主要文本输入法 – 用于指定可用于进行输入的硬件键类型。 可能的值为:

    • nokeys – 没有可用于进行输入的硬件键。

    • qwerty – 有可用的 qwerty 键盘。

    • 12key – 有 12 键的硬件键盘

  • 导航键可用性 – 当五向或方向键导航可用时。 这可能在应用程序的生存期内发生变化。 可能的值为:

    • navexposed – 导航键可供用户使用

    • navhidden – 导航键不可用。

  • 主要非触摸导航方法 – 设备上可用的导航类型。 可能的值为:

    • nonav – 唯一可用的导航设施是触摸屏

    • dpad – 方向键可用于导航

    • trackball – 设备具有用于导航的轨迹球

    • wheel – 存在一个或多个方向轮的不常见情况

  • 平台版本(API 级别)– 设备支持的 vN 格式的 API 级别,其中 N 是所面向的 API 级别。 例如,v11 将面向 API 级别 11 (Android 3.0) 设备。

有关资源限定符的详细信息,请参阅 Android 开发人员网站上的提供资源

Android 如何确定要使用的资源

Android 应用程序很可能包含许多资源。 了解 Android 如何在应用程序在设备上运行时为其选择资源非常重要。

Android 通过循环访问以下规则测试来确定资源基础:

  • 消除矛盾限定符 – 例如,如果设备方向为竖屏,则所有横屏资源目录都将被拒绝。

  • 忽略不支持的限定符 – 并非所有限定符都可用于所有 API 级别。 如果资源目录包含设备不支持的限定符,则将忽略该资源目录。

  • 确定下一个优先级最高的限定符 – 参考上表选择下一个优先级最高的限定符(从上到下)。

  • 保留限定符的所有资源目录 – 前提是有资源目录可将限定符与上表匹配。选择下一个优先级最高的限定符(从上到下)。

这些规则还在以下流程图中进行了说明:

Resources flowchart

当系统查找特定于密度的资源但找不到时,它将尝试查找其他特定于密度的资源并缩放这些资源。 Android 不一定使用默认资源。 例如,当查找低密度资源但其不可用时,Android 可能会选择高密度版本的资源,而不是默认或中等密度的资源。 这样做是因为高密度资源可以缩减二分之一(系数为 0.5),与缩减中等密度的资源(需要的系数为 0.75)相比,这样导致的可见性问题更少。

例如,请考虑具有以下可绘制资源目录的应用程序:

drawable
drawable-en
drawable-fr-rCA
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

现在,该应用程序在具有以下配置的设备上运行:

  • 区域设置 – en-GB
  • 方向 – port
  • 屏幕密度 – hdpi
  • 触摸屏类型 – notouch
  • 主输入法 – 12key

首先,由于法语资源与 en-GB 的区域设置相冲突,因此法语资源被删除,留给我们的是:

drawable
drawable-en
drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi
drawable-port-ldpi
drawable-port-notouch-12key

接下来,从上面的限定符表中选择第一个限定符:MCC 和 MNC。 没有包含此限定符的资源目录,因此忽略 MCC/MNC 代码。

选择下一个限定符,即语言。 有与语言代码匹配的资源。 拒绝与语言代码 en 不匹配的所有资源目录,因此资源列表现在为:

drawable-en-port
drawable-en-notouch-12key
drawable-en-port-ldpi

存在的下一个限定符针对的是屏幕方向,因此将删除与屏幕方向 port 不匹配的所有资源目录:

drawable-en-port
drawable-en-port-ldpi

下一个是针对屏幕密度的限定符 ldpi,这会导致再排除一个资源目录而得到以下结果:

drawable-en-port-ldpi

在此过程结束后,Android 将为设备使用资源目录 drawable-en-port-ldpi 中的可绘制资源。

注意

屏幕大小限定符对此选择过程提供了一个例外。 Android 可以选择适用于比当前设备的屏幕更小的屏幕的资源。 例如,大屏幕设备可以使用为普通大小的屏幕提供的资源。 但反之则不可以:同一个大屏幕设备不会使用为超大屏幕提供的资源。 如果 Android 找不到与给定屏幕大小匹配的资源集,应用程序将会崩溃。