Android - 资源
Android 资源:组织与访问
Section titled “Android 资源:组织与访问”构建健壮的 Android 应用不仅仅是编写 Kotlin 或 Java 代码。你还需要管理代码使用的各种静态资源,例如图像、颜色、布局定义、用户界面字符串、动画、字体等。这些资源被保存在项目 res/ 目录下的独立子目录中。
本教程将指导你如何组织应用程序资源,为不同的设备配置指定备选资源,以及如何在现代 Android 应用中高效地访问它们。
在 Android Studio 中组织资源
Section titled “在 Android Studio 中组织资源”Android Studio 中典型的 Android 项目结构组织资源如下:
MyProject/ app/ src/ main/ AndroidManifest.xml java/ com/example/myproject/ MyActivity.java res/ animator/ (属性动画的 XML 文件,例如 objectAnimator) anim/ (旧式补间动画的 XML 文件 - 现在不太常用) color/ (定义状态列表颜色的 XML 文件) drawable/ (位图文件:.png, .jpg, .gif;形状、矢量图、状态列表的 XML 文件) font/ (字体文件:.ttf, .otf,或定义字体家族的 XML 文件) layout/ (定义 UI 布局的 XML 文件) menu/ (选项菜单、上下文菜单的 XML 文件) mipmap/ (特定密度启动器图标:icon.png) navigation/ (Jetpack Navigation 导航图的 XML 文件) raw/ (以原始形式保存的任意文件) values/ (简单值的 XML 文件:strings.xml, colors.xml, dimens.xml, styles.xml, themes.xml) xml/ (任意 XML 配置文件)以下是常见资源目录及其类型的细分:
| 编号 | 目录 & 资源类型 |
|---|---|
| 1 | animator/ 定义属性动画的 XML 文件(例如,使用 <objectAnimator>、<valueAnimator>)。保存在 res/animator/ 中,通过 R.animator 访问。 |
| 2 | anim/ 定义旧式补间动画的 XML 文件。保存在 res/anim/ 中,通过 R.anim 访问。通常更偏好 animator/ 中的属性动画,因为它更灵活。 |
| 3 | color/ 定义颜色状态列表(例如,用于按钮状态)或简单颜色资源的 XML 文件。保存在 res/color/ 中,通过 R.color 访问。 |
| 4 | drawable/ 图像文件(例如, .png、.jpg、.webp)或编译为 drawable 资源的 XML 文件(例如,形状、矢量图、状态列表 drawable、渐变)。保存在 res/drawable/ 中,通过 R.drawable 访问。强烈推荐使用矢量图来获得与分辨率无关的图形。 |
| 5 | font/ 字体文件(例如, .ttf、.otf)或定义字体家族的 XML 文件。保存在 res/font/ 中,通过 R.font 访问。 |
| 6 | layout/ 定义用户界面结构的 XML 文件(例如,用于 Activity 或 Fragment)。保存在 res/layout/ 中,通过 R.layout 访问。 |
| 7 | menu/ 定义应用菜单的 XML 文件(例如,选项菜单、上下文菜单)。保存在 res/menu/ 中,通过 R.menu 访问。 |
| 8 | mipmap/ 主要用于特定密度的应用启动器图标。Android 系统使用这些图标为设备屏幕选择最佳分辨率图标。通过 R.mipmap 访问。 |
| 9 | navigation/ 使用 Jetpack Navigation 组件的应用定义导航图的 XML 文件。保存在 res/navigation/ 中,通过 R.navigation 访问。 |
| 10 | raw/ 以原始形式保存的任意文件(例如,音频、视频文件)。使用 Resources.openRawResource() 和 R.raw.filename 访问。 |
| 11 | values/ 包含简单值(如字符串、尺寸、颜色、样式和主题)的 XML 文件。常见文件名包括: - strings.xml: 字符串值 (R.string)。- colors.xml: 颜色定义 (R.color)。- dimens.xml: 尺寸值 (R.dimen)。- styles.xml: UI 样式 (R.style)。- themes.xml: 应用或 Activity 主题(对于 Material Design 3,通常位于 res/values/themes/ 和 res/values-night/themes/ 中)。- arrays.xml: 资源数组 (R.array)。- attrs.xml: 自定义视图的自定义属性。 |
| 12 | xml/ 可在运行时使用 Resources.getXml() 读取的任意 XML 文件。对于配置数据非常有用。 |
现代 Android 应用必须适应各种各样的设备。你应该提供备选资源来支持特定的设备配置,例如不同的屏幕尺寸、密度、方向、语言和 UI 模式(如深色主题)。
要指定特定于配置的备选资源:
- 在
res/中创建一个名为<资源名称>-<配置限定符>的新目录。例如,对于最小宽度为 600dp 的屏幕,使用layout-sw600dp作为布局,或者对于西班牙语字符串使用values-es。 <资源名称>是标准资源类型(例如,drawable、layout、values)。<配置限定符>指定配置(例如,land代表横向,hdpi代表高密度,night代表夜间模式)。你可以组合多个限定符(例如,drawable-en-land-hdpi)。- 将备选资源文件保存在此新目录中。这些文件必须与默认资源文件具有完全相同的名称。Android 会在运行时根据当前设备配置自动加载适当的资源。
示例:为不同屏幕密度提供不同的 drawable 资源,并提供矢量图作为默认(或适用于所有密度,如果设计允许):
MyProject/ app/src/main/ res/ drawable/ (默认,通常用于矢量图或 -nodpi 资源) icon.xml (矢量图) background.png drawable-mdpi/ (中等密度 ~160dpi) background.png drawable-hdpi/ (高密度 ~240dpi) background.png drawable-xhdpi/ (超高密度 ~320dpi) background.png drawable-xxhdpi/ (超超高密度 ~480dpi) background.png drawable-xxxhdpi/ (超超超高密度 ~640dpi) background.png mipmap-anydpi-v26/ (用于自适应图标) ic_launcher.xml mipmap-hdpi/ ic_launcher.png (遗留启动器图标) ...提示:对于大多数图标和简单图形,使用矢量图(drawable/ 目录中的 .xml 文件)。它们可以无损缩放并减小 APK 大小。对于启动器图标,使用自适应图标,并在 mipmap 目录中提供遗留版本。
示例:为纵向和横向提供不同的布局,以及为英语(默认)和阿拉伯语提供不同的字符串:
MyProject/ app/src/main/ res/ layout/ (默认布局 - 通常为纵向) activity_main.xml layout-land/ (横向布局) activity_main.xml values/ (默认字符串 - 通常为英语) strings.xml values-ar/ (阿拉伯语字符串) strings.xml (如果在 Manifest 中设置了 android:supportsRtl="true",则自动支持从右到左的布局)常用限定符包括:语言和区域(-en、-fr-rCA)、最小宽度(-sw<N>dp)、可用宽度/高度(-w<N>dp、-h<N>dp)、屏幕方向(-land、-port)、UI 模式(-night、-car)、API 级别(-v21)。请参考官方 Android 文档,获取完整的限定符列表和提供备选资源的最佳实践。
你需要在 Kotlin/Java 代码或 XML 文件中访问定义的资源。
在代码中访问资源
Section titled “在代码中访问资源”编译 Android 应用时,会生成一个 R 类。此类包含项目中 res/ 目录下所有资源的静态整数 ID。你使用这些 ID 来访问资源。
示例:在 Activity 中为 ImageView 设置图像并为 TextView 设置文本(使用 View Binding,这是与视图交互的推荐方式):
首先,在你的模块级 build.gradle.kts(或 build.gradle)文件中启用 View Binding:
// build.gradle.kts (Groovy: buildFeatures { viewBinding true })android { // ... buildFeatures { viewBinding = true }}然后,在你的 Activity(例如,MyActivity.java)中:
package com.example.myproject;
import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;// 假设你的布局文件是 activity_my.xml,则会生成此类import com.example.myproject.databinding.ActivityMyBinding;
public class MyActivity extends AppCompatActivity {
private ActivityMyBinding binding; // ViewBinding 对象
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 膨胀布局并获取绑定对象 binding = ActivityMyBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot());
// 使用绑定对象访问视图(例如,如果你有一个 id 为 'myImageView' 的 ImageView) // binding.myImageView.setImageResource(R.drawable.my_image_name);
// 原始上下文示例:假设有一个 id 为 'myImageViewInXml' 的 ImageView binding.myImageViewInXml.setImageResource(R.drawable.myimage); // R.drawable.myimage 指代 res/drawable/myimage.png (或 .xml)
// 假设有一个 id 为 'messageTextViewInXml' 的 TextView binding.messageTextViewInXml.setText(R.string.hello_message); // R.string.hello_message 指代 strings.xml 中的一个字符串
// 获取颜色资源(例如,来自 res/values/colors.xml): // int myColor = ContextCompat.getColor(this, R.color.my_custom_color); // binding.messageTextViewInXml.setTextColor(myColor); }}在此示例中,R.drawable.myimage 指代位于 res/drawable* 目录中的图像文件(例如,myimage.png 或 myimage.xml)。R.string.hello_message 指代在 res/values/strings.xml 中定义的名为 hello_message 的字符串资源。
示例:包含 hello_message 的 res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <string name="app_name">My Application</string> <string name="hello_message">Hello from Resources!</string></resources>示例:在 Activity 的 onCreate() 方法中加载布局:
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 这会加载 res/layout/activity_main.xml 中定义的布局 setContentView(R.layout.activity_main); }}在 XML 中访问资源
Section titled “在 XML 中访问资源”你还可以使用 @ 符号直接在 XML 文件中(例如,布局、样式、drawable)引用资源。
语法:@<包名>:<资源类型>/<资源名称>
- 如果资源来自你自己的应用,则
<包名>是可选的(通常省略)。 <资源类型>是R的子类(例如,string、drawable、color、dimen)。<资源名称>是资源文件的名称(不带扩展名)或 XML 资源文件中的name属性值。
示例:res/values/colors.xml 和 res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?><resources> <color name="app_primary_color">#FF6200EE</color> <color name="text_error_red">#B00020</color></resources>
<!-- res/values/strings.xml --><?xml version="1.0" encoding="utf-8"?><resources> <string name="greeting">Hello World!</string> <string name="submit_button_text">Submit</string></resources>示例:在布局文件(例如,res/layout/activity_main.xml)中使用这些资源:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/activity_padding"> <!-- 假设 @dimen/activity_padding 在 dimens.xml 中 -->
<TextView android:id="@+id/greetingTextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/greeting" android:textColor="@color/app_primary_color" android:textSize="@dimen/text_size_large" /> <!-- 假设 @dimen/text_size_large 在 dimens.xml 中 -->
<Button android:id="@+id/submitButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/submit_button_text" android:backgroundTint="@color/app_primary_color" />
</LinearLayout>注意使用 ?attr/ 来引用主题属性(例如,android:textColor="?attr/colorPrimary"),这是创建可主题化 UI 的强大方法。当颜色应适应应用主题时,这比直接硬编码颜色更可取。
理解如何组织和访问资源对于 Android 开发至关重要,使你能够创建灵活、可维护和适应性强的应用程序。