Android Studio 添加应用资源

前一小节我们介绍了如何使用 Android Studio 布局编辑器,本小结我们学习 Android 的应用资源类型、备用资源限定和资源合并相关的知识。

1. 应用资源的类型

应用资源是指代码使用的附加文件和静态内容,例如位图、布局定义、界面字符串、动画等。应用资源分很多种:

  • 动画资源:定义预先确定的动画,补间动画保存在 res/anim/ 中,帧动画保存在 res/drawable/ 中;

  • 颜色状态列表资源:定义根据 View 状态而变化的颜色资源,保存在 res/color/ 中;

  • 可绘制资源:使用位图或 XML 定义各种图形,保存在 res/drawable/ 中;

  • 布局资源:定义应用界面的布局,保存在 res/layout/ 中;

  • 菜单资源:定义应用菜单的内容,保存在 res/menu/ 中;

  • 字符串资源:定义字符串、字符串数组,保存在 res/values/ 中;

  • 样式资源:定义界面元素的外观和格式,保存在 res/values/ 中;

  • 字体资源:在 XML 中定义字体系列并包含自定义字体,保存在 res/font/ 中。

我们应将各类资源放入项目 res/ 目录的特定子目录中。例如,以下是一个简单项目的文件层次结构:

FirstApp/
    src/
        MainActivity.java
    res/
        drawable/
            graphic.png
        layout/
            main.xml
            info.xml
        mipmap/
            icon.png
        values/
            strings.xml

Tips:res/ 目录包含所有资源:一个图像资源、两个布局资源、启动器图标资源以及一个字符串资源文件。

资源目录名称非常重要,项目 res/ 目录中支持的资源目录见下表:

目录 资源类型
animator/ 用于定义属性动画的 XML 文件。
anim/ 用于定义补间动画的 XML 文件。
color/ 用于定义颜色状态列表的 XML 文件。
drawable/ 位图文件或可绘制对象资源子类型的 XML 文件
mipmap/ 适用于不同启动器图标密度的可绘制对象文件。
layout/ 用于定义用户界面布局的 XML 文件。
menu/ 用于定义应用菜单(如选项菜单、上下文菜单或子菜单)的 XML 文件。
raw/ 需以原始形式保存的任意文件。
values/ 包含字符串、整型数和颜色等简单值的 XML 文件。
xml/ 可在运行时读取的任意 XML 配置文件。
font/ 带有扩展名的字体文件或包含 元素的 XML 文件。

上表所列的目录中,保存的资源为“默认”资源,即这些资源定义应用的默认设计和内容,除默认资源以外,我们还需提供备用资源。

2. 应用备用资源

不同类型的 Android 设备可能需要不同类型的资源。例如,如果设备屏幕比标准屏幕大,则应提供不同的布局资源,从而充分利用额外的屏幕空间;如果设备的语言设置不同,则应提供不同的字符串资源,以便将界面中的文本转换为其他语言。在运行时,Android 会检测当前设备配置并为应用加载合适的资源。

我们如何为一组资源指定配置特定的备用资源呢?分两步:

  1. 在 res/ 中创建以 < resources_name >-< config_qualifier > 形式命名的新目录;
    • < resources_name > 是相应默认资源的目录名称;
    • < config_qualifier > 是指定要使用这些资源的各个配置限定符的名称。
  2. 将相应的备用资源保存在此新目录下,这些资源文件必须与默认资源文件完全同名。

例如,以下是一些默认资源和屏幕像素密度备用资源:

res/
    drawable/
        icon.png
        background.png
    drawable-hdpi/
        icon.png
        background.png

hdpi 限定符表示该目录中的资源适用于屏幕密度较高的设备。其中,每个可绘制对象目录中的图像均已针对特定的屏幕密度调整了大小,但文件名完全相同。如此一来,用于引用 icon.png 或 background.png 图像的资源 ID 始终相同,但 Android 会通过将设备配置信息与资源目录名称中的限定符进行比较,选择最符合当前设备的各个资源版本。

Android 支持若干配置限定符,我们可以通过使用短划线分隔每个限定符,从而向一个目录名称添加多个限定符。下表按优先级顺序列出了有效的配置限定符;如果对资源目录使用多个限定符,则必须按照表中所列顺序将其添加到目录名称中。

配置 描述
MCC 和 MNC 移动设备国家代码 (MCC),(可选)后跟设备 SIM 卡中的移动设备网络代码 (MNC)。
语言和区域 语言通过由两个字母组成的 ISO 639-1 语言代码进行定义,可以选择后跟两个字母组成的 ISO 3166-1-alpha-2 区域码(前缀用小写字母 r)。
布局方向 应用的布局方向。ldrtl 是指“布局方向从右到左”。
smallestWidth 屏幕的基本尺寸,由可用屏幕区域的最小尺寸指定。
可用宽度 指定资源应使用的最小可用屏幕宽度。
可用高度 指定资源应使用的最小可用屏幕高度。
屏幕尺寸 屏幕是小尺寸、标准尺寸还是大尺寸。
屏幕纵横比 屏幕是否为宽屏。
圆形屏幕 屏幕是否为圆形屏幕。
广色域 屏幕是否具有广色域。
高动态范围 屏幕是否具有 HDR 功能。
屏幕方向 当前的设备方向。类似 port,land。
夜间模式 是否夜间模式。
屏幕像素密度 屏幕分辨率与屏幕尺寸的比值。类似 ldpi,mdpi,hdpi,xhdpi 等。
平台版本(API 级别) 设备支持的 API 级别。

3. 添加应用资源

Android Studio 可以帮助我们通过多种方式添加新资源和备用资源,具体取决于我们要添加的资源的类型。接下来我们学习如何添加基本的资源文件、如何更改资源的位置以及资源合并的原理。

3.1 添加 XML 资源文件

如果我们需要添加任何 XML 资源文件,请按照以下步骤操作:

点击 Project 窗口中的目标应用模块(在 AndroidProject 视图中时),然后依次选择 File > New > Android resource file

在对话框中填写详细信息:

  • File name:输入 XML 文件的名称(不需要输入 .xml 后缀);

  • Resource type:选择要创建的资源的类型;

  • Root element:为文件选择根 XML 元素(如果适用)。某些资源类型仅支持一种类型的根元素,因此这项可能无法修改,具体取决于上面选择的资源类型;

  • Source set:选择要将文件保存到的源代码集;

  • Directory name:目录命名方式必须特定于资源类型和配置限定符;

  • Available qualifiers:我们可以选择左侧列表中的限定符。

添加完所需的所有限定符之后,点击 OK

3.2 添加资源目录

如果我们需要添加新的资源目录,请按照以下步骤操作:

点击 Project 窗口中的目标应用模块,然后依次选择 File > New > Android resource directory

在对话框中填写详细信息:

  • Directory name:目录命名方式必须特定于资源类型以及配置限定符的组合。

  • Resource type:选择要创建的资源的类型。

  • Source set:选择要将布局保存到的源代码集。

  • Available qualifiers:我们可以选择左侧列表中的限定符。
    添加完所需的所有限定符之后,点击 OK

3.3 更改资源目录

默认情况下,我们的资源位于 module-name/src/source-set-name/res/。例如,模块的主源代码集的资源位于 src/main/res/,调试源代码集的资源则位于 src/debug/res/。

不过,我们可以使用 sourceSets {} 块中的 res.srcDirs 属性将这些路径更改为任何其他位置(相对于 build.gradle 文件)。例如:

android {
    sourceSets {
        main {
            res.srcDirs = ['resources/main']
        }
        debug {
            res.srcDirs = ['resources/debug']
        }
    }
}

我们还可以为一个源代码集指定多个资源目录,构建工具会将它们合并在一起。例如:

android {
    sourceSets {
        main {
            res.srcDirs = ['res1', 'res2']
        }
    }
}

3.4 资源合并原理

最终 APK 文件中的资源可能有 3 个不同的来源:

  • 主源代码集(通常位于 src/main/res/);

  • 构建变体源代码集;

  • Android 库 (AAR)。

如果来自各个源代码集或库的所有资源都是唯一的,则它们均会添加到最终 APK 中。如果某项资源的文件名在其资源类型目录和资源限定符(如果已定义)中都是唯一的,系统即会将该资源视为唯一的。

如果存在同一资源的两个或多个匹配版本,则只有一个版本会包含在最终 APK 中。构建工具会根据以下优先级顺序(左侧的优先级最高)选择要保留的版本:

构建变体 > build 类型 > 产品变种 > 主源代码集 > 库依赖项

例如,如果主源代码集包含:

  • res/layout/foo.xml

  • res/layout-land/foo.xml

并且调试 build 类型包含:

  • res/layout/foo.xml

则最终 APK 会包括来自调试 build 类型的 res/layout/foo.xml 和来自主源代码集的 res/layout-land/foo.xml。

Tips:当我们的构建配置为一个给定的源代码集指定了多个资源文件夹时,如果这些来源之间存在冲突,则会发生错误,并且合并会失败,因为各个资源目录的优先级相同。

4. 小结

本节课程我们主要学习了 Android 的应用资源类型、备用限定及如何添加资源。本节课程的重点如下:

  • 掌握应用资源的分类和备用资源限定符;
  • 掌握添加资源和资源合并的原理。