资源体系
本教程共 100 篇 · 第 23 篇 · 更新于 2026-07-28 · 约 9 分钟阅读
23. 资源体系
本节目标:搞懂 Android 的资源体系,知道 res 下每个目录放什么、values 里怎么组织字符串颜色主题、drawable 和 mipmap 区别、资源限定符怎么实现多语言多屏幕适配。
为什么要资源体系
Android 把「代码」和「资源」分开。资源包括字符串、颜色、图片、布局、动画、尺寸等,放在 res/ 下。好处:
- 多语言:不同语言用不同
strings.xml,代码不变。 - 多屏幕:不同密度、尺寸用不同图片和布局。
- 主题切换:浅色深色主题靠资源切换。
- 复用:一处定义,处处引用。
- 编译检查:资源 ID 在编译期生成,引用错会报错。
代码里通过 R.类型.名字 引用资源,如 R.string.app_name、R.color.primary。
res 目录总览
res/
├── values/ 字符串、颜色、尺寸、主题、数组
│ ├── strings.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── themes.xml
│ └── arrays.xml
├── drawable/ 图片、矢量图、形状、选择器
├── mipmap-mdpi/ 应用图标(按密度)
├── mipmap-hdpi/
├── mipmap-xhdpi/
├── mipmap-xxhdpi/
├── mipmap-xxxhdpi/
├── layout/ XML 布局(传统 View 用)
├── font/ 字体
├── anim/ 补间动画 XML
├── animator/ 属性动画 XML
├── xml/ 配置文件(备份规则、FileProvider 路径等)
├── raw/ 原始文件(音频、视频、JSON)
└── menu/ 菜单 XML
values:值资源
strings.xml
字符串集中管理,方便多语言:
<resources>
<string name="app_name">我的应用</string>
<string name="welcome">欢迎,%1$s!您有 %2$d 条消息</string>
<string-array name="weekdays">
<item>周一</item>
<item>周二</item>
<item>周三</item>
</string-array>
</resources>
代码里用:
val name = getString(R.string.app_name)
val msg = getString(R.string.welcome, "张三", 5) // 带格式化参数
val days = resources.getStringArray(R.array.weekdays)
XML 里引用:android:text="@string/app_name"
Tip
- 不要在代码里硬编码字符串。所有用户可见文字都放
strings.xml,方便国际化,也便于统一修改。
colors.xml
<resources>
<color name="primary">#6750A4</color>
<color name="on_primary">#FFFFFF</color>
<color name="error">#B3261E</color>
<color name="background">#FFFBFE</color>
</resources>
引用:android:textColor="@color/primary" 或代码 ContextCompat.getColor(context, R.color.primary)。
dimens.xml
<resources>
<dimen name="spacing_small">8dp</dimen>
<dimen name="spacing_medium">16dp</dimen>
<dimen name="spacing_large">24dp</dimen>
<dimen name="text_title">20sp</dimen>
</resources>
引用:android:padding="@dimen/spacing_medium"。
尺寸单位:
dp(density-independent pixel):密度无关像素,用于布局尺寸,不同屏幕密度下视觉一致。sp(scale-independent pixel):可缩放像素,用于文字,会跟随用户字体大小设置。px:像素,不用,不同屏幕不一致。
themes.xml
主题定义应用整体样式:
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Theme.MyApp" parent="android:Theme.Material.Light.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorOnPrimary">@color/on_primary</item>
<item name="android:statusBarColor">@color/primary</item>
</style>
</resources>
Compose 项目主题主要在 Kotlin 里定义(MaterialTheme),但 Manifest 的 android:theme 还是要指向一个 XML 主题,影响启动闪屏和系统 UI 颜色。
drawable:图形资源
drawable/ 放所有可绘制资源:
- 位图:
.png、.jpg、.webp、.gif。 - 矢量图:
.xml,<vector>标签,任意缩放不失真,体积小。 - 形状:
.xml,<shape>定义矩形、圆角、渐变、描边。 - 选择器:
.xml,<selector>按状态显示不同图(按下、选中)。 - 图层列表:
<layer-list>叠加多个图。
<!-- 圆角矩形背景 -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
</shape>
<!-- 按钮状态选择器 -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@color/primary_dark" />
<item android:drawable="@color/primary" />
</selector>
Note
- 优先用矢量图(VectorDrawable)代替位图,体积小、任意密度都清晰。Android Studio 能把 SVG 转 VectorDrawable(右键 drawable -> New -> Vector Asset)。
mipmap:应用图标
应用图标放 mipmap-*/,按密度分目录:
| 目录 | 密度 | 倍数 |
|---|---|---|
mipmap-mdpi | ~160dpi | 1x |
mipmap-hdpi | ~240dpi | 1.5x |
mipmap-xhdpi | ~320dpi | 2x |
mipmap-xxhdpi | ~480dpi | 3x |
mipmap-xxxhdpi | ~640dpi | 4x |
Tip
- 图标放
mipmap而不是drawable,因为 launcher 可能用比设备密度更高的图标(如大屏 launcher)。其他图片放drawable。
Android Studio 用 Image Asset Studio 生成图标:右键 res -> New -> Image Asset,能自动生成各密度版本和自适应图标(Adaptive Icon)。
资源限定符:备选资源
Android 根据设备配置(语言、屏幕、版本、夜间模式)自动选最合适的资源。机制是在 res/ 下建带限定符后缀的目录。
多语言
res/
├── values/ 默认(通常英文或中文)
│ └── strings.xml
├── values-zh/ 中文
│ └── strings.xml
├── values-zh-rTW/ 中文-台湾
│ └── strings.xml
└── values-ja/ 日文
└── strings.xml
系统根据设备语言自动选。设备是中文,用 values-zh 里的;没有就回退到默认 values。
屏幕密度
res/
├── drawable-mdpi/
├── drawable-hdpi/
├── drawable-xhdpi/
├── drawable-xxhdpi/
└── drawable-xxxhdpi/
放对应密度的位图,系统按设备密度选。矢量图放 drawable/(不限定符),所有密度通用。
屏幕尺寸与方向
res/
├── layout/ 默认
├── layout-land/ 横屏
├── layout-sw600dp/ 最小宽度 600dp(平板)
└── layout-w600dp/ 当前宽度 600dp(大屏)
夜间模式
res/
├── values/ 默认(浅色)
│ └── themes.xml
└── values-night/ 深色模式
└── themes.xml
Android 10+ 系统深色模式切换时,系统自动用 values-night 资源。
版本限定
res/
├── values/
└── values-v29/ API 29+ 用
限定符优先级
多个限定符组合时,顺序很重要,按官方规定顺序写:
MCC/MNC > 语言 > 布局方向 > 最小宽度 > 当前宽度 > 当前高度 > 屏幕尺寸 > 屏幕纵横比 > 圆角 > 屏幕方向 > UI 模式 > 夜间模式 > 像素密度 > 触摸屏 > 键盘 > 文本输入法 > 导航 > 屏幕尺寸(旧) > 平台版本
日常常用的就语言、密度、夜间模式、屏幕方向、版本,组合时注意顺序。
资源引用方式
XML 里
<TextView
android:text="@string/app_name"
android:textColor="@color/primary"
android:background="@drawable/bg_rounded"
android:textSize="@dimen/text_title" />
@[包:]类型/名字。引用系统资源用 @android:color/black,引用风格 ?attr/colorPrimary。
代码里
val name = getString(R.string.app_name)
val color = ContextCompat.getColor(context, R.color.primary)
val drawable = ContextCompat.getDrawable(context, R.drawable.bg)
val size = resources.getDimension(R.dimen.spacing_medium)
Compose 里用 stringResource、colorResource 等可组合函数:
@Composable
fun Greeting() {
val name = stringResource(R.string.app_name)
val color = colorResource(R.color.primary)
Text(text = name, color = color)
}
assets:原始资源
assets/ 和 res/ 区别:
assets/里的文件原样打包,不生成 ID,不参与编译。- 通过
AssetManager访问,路径是字符串。
适合放需要原样读取的文件(JSON 配置、字体、HTML、数据库预填数据):
context.assets.open("config.json").use { input ->
val text = input.bufferedReader().readText()
}
常见操作
| 想干什么 | 怎么做 |
|---|---|
| 加字符串 | strings.xml 加 <string> |
| 加颜色 | colors.xml 加 <color> |
| 加图片 | 拖到 drawable/ 或用 Vector Asset |
| 改应用名 | 改 strings.xml 的 app_name |
| 加多语言 | 新建 values-zh/strings.xml |
| 加夜间主题 | 新建 values-night/themes.xml |
| 引用资源 | XML 用 @type/name,代码用 R.type.name |
小结
资源放 res/,按类型分目录:values(字符串/颜色/尺寸/主题)、drawable(图形)、mipmap(图标)、layout(布局)、raw(原始文件)。资源限定符后缀(语言、密度、夜间、屏幕)实现多设备适配。代码用 R.type.name 引用,XML 用 @type/name。assets 放原样文件。第 3 部分结束,下一部分学 Activity。