3、Android资源目录结构:res目录详解

说到Android的资源管理,res目录绝对是绕不开的核心。我个人习惯把res目录比作一个「资源仓库」——你所有用到的图片、布局、字符串、颜色、尺寸,全得往这里面塞。今天我就带你把res目录翻个底朝天。

3.1 res目录到底长什么样?

先看一个典型的res目录结构:

res/
├── drawable/          # 位图、XML图形、形状
├── mipmap/            # 应用图标(启动图标)
├── values/            # 字符串、颜色、尺寸、主题
├── layout/            # 布局文件
├── anim/              # 补间动画
├── animator/          # 属性动画
├── color/             # 颜色状态列表
├── font/              # 自定义字体
├── menu/              # 菜单定义
├── raw/               # 原始资源(音频、视频等)
├── xml/               # 任意XML文件
└── transition/        # 场景过渡动画

嗯,这里要注意:mipmap和drawable的区别。很多新手会搞混。mipmap专门放应用启动图标,drawable放其他图片资源。为什么分开?因为启动图标在不同密度下需要特殊处理,系统会保留所有密度版本,而drawable可能会被压缩。

核心原则:应用图标放mipmap,其他图片放drawable。别混着放,否则打包时可能出问题。

3.2 drawable目录详解

drawable是我打交道最多的目录。它不只是放图片那么简单。你想想看,它还能放XML定义的形状、渐变、选择器。

举个例子,一个圆角按钮的背景:

<!-- res/drawable/rounded_button.xml -->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="8dp" />
    <solid android:color="#FF6200EE" />
    <padding
        android:left="16dp"
        android:top="8dp"
        android:right="16dp"
        android:bottom="8dp" />
</shape>

我在项目中遇到过一个问题:团队里有人把一张超大PNG直接丢进drawable,结果APK体积暴涨。后来我们统一用WebP格式,体积直接砍半。说白了,drawable里的图片格式选择很重要。

我的建议:能用VectorDrawable就用矢量图,实在不行用WebP。PNG只保留必要的透明度场景。

3.3 mipmap目录的秘密

mipmap目录下通常有多个密度版本:

mipmap-mdpi/      # 1x
mipmap-hdpi/      # 1.5x
mipmap-xhdpi/     # 2x
mipmap-xxhdpi/    # 3x
mipmap-xxxhdpi/   # 4x
mipmap-anydpi-v26/ # 自适应图标

为什么要保留所有密度?因为启动图标在桌面显示时,系统会从mipmap中选取最合适的版本。如果你只放了一个mdpi版本,在高密度屏幕上会模糊得一塌糊涂。

我曾经踩过一个坑:为了省事,只放了xxhdpi的图标,结果在旧设备上图标显示异常。嗯,从那以后我老老实实生成所有密度版本。

3.4 values目录:资源的核心

values目录存放的是「值资源」,说白了就是各种常量定义。常见的文件有:

文件名 用途 示例
strings.xml 字符串 <string name="app_name">我的应用</string>
colors.xml 颜色值 <color name="primary">#FF6200EE</color>
dimens.xml 尺寸值 <dimen name="margin">16dp</dimen>
styles.xml 样式/主题 <style name="AppTheme">...</style>
arrays.xml 数组 <string-array name="planets">...</string-array>

我个人习惯把颜色和尺寸单独抽出来,而不是硬编码在布局里。为什么?因为后期改主题色时,你只需要改colors.xml里的一个值,而不是翻遍所有布局文件。

注意:values目录下的文件名可以自定义,但建议遵循Android Studio的默认命名。别搞什么my_custom_values.xml,团队协作时别人根本找不到。

3.5 资源限定符:让资源适配不同设备

资源限定符是Android资源管理的精髓。说白了,就是根据设备的不同特性,自动加载对应的资源文件。

常见的限定符分类:

  • 密度限定符:mdpi、hdpi、xhdpi、xxhdpi、xxxhdpi、nodpi、tvdpi
  • 语言限定符:en、zh、zh-rCN、de、fr 等
  • 屏幕尺寸限定符:small、normal、large、xlarge
  • 屏幕方向限定符:port、land
  • API级别限定符:v14、v21、v26 等
  • 夜间模式限定符:night、notnight
  • 布局方向限定符:ldrtl、ldltr

举个例子,多语言适配:

res/
├── values/strings.xml           # 默认(英语)
├── values-zh/strings.xml        # 中文
├── values-zh-rCN/strings.xml    # 简体中文
├── values-de/strings.xml        # 德语
└── values-fr/strings.xml        # 法语

系统会根据设备的语言设置,自动选择对应的strings.xml。你想想看,这比在代码里写if-else判断语言方便多了。

3.6 密度限定符实战

密度限定符是最常用的。Android设备屏幕密度五花八门,从ldpi到xxxhdpi都有。正确的做法是:

res/
├── drawable-mdpi/       # 基准密度
├── drawable-hdpi/       # 1.5倍
├── drawable-xhdpi/      # 2倍
├── drawable-xxhdpi/     # 3倍
└── drawable-xxxhdpi/    # 4倍

我在项目中遇到过一个问题:设计师只给了xxhdpi的切图,结果在mdpi设备上显示时,图片被缩小了3倍,边缘锯齿明显。后来我要求设计师至少提供mdpi、xhdpi、xxhdpi三套图。

避坑指南:我曾经把一张背景图放在drawable-nodpi里,结果在不同密度设备上显示大小不一致。nodpi的意思是「不缩放」,但图片的物理像素不变,在不同密度下实际显示尺寸会变。正确做法是用dimens定义尺寸,图片放在对应密度目录下。

3.7 限定符的匹配规则

系统选择资源时,遵循「最匹配优先」原则。举个例子:

  • 设备是中文、xxhdpi、横屏
  • 系统会优先找 values-zh-xxhdpi-land/
  • 找不到就降级到 values-zh-xxhdpi/
  • 再找不到就 values-zh/
  • 最后才是 values/

说白了,限定符越多越精确,但也要考虑降级路径。我建议不要搞太多层限定符,否则维护起来很痛苦。

3.8 资源引用方式

在代码和XML中引用资源:

// Java/Kotlin 代码中
getResources().getString(R.string.app_name)
getResources().getDrawable(R.drawable.ic_launcher)
getResources().getColor(R.color.primary)

// XML 布局中
@string/app_name
@drawable/ic_launcher
@color/primary
@dimen/margin

嗯,这里有个小技巧:在Flutter中引用Android资源时,需要通过MethodChannel或者使用flutter_native_resource插件。不过大多数情况下,Flutter有自己的资源管理方式,Android的res目录主要用于原生模块。

3.9 知识体系总览

下面这张图帮你理清res目录的核心逻辑:

res 资源目录 drawable 位图、XML图形、形状 支持密度限定符 mipmap 应用启动图标 保留所有密度版本 values 字符串、颜色、尺寸 支持语言限定符 layout / anim / menu raw / xml / font color / transition 资源限定符体系 密度限定符:mdpi | hdpi | xhdpi | xxhdpi | xxxhdpi 语言限定符:en | zh | zh-rCN | de | fr | ja 屏幕方向:port(竖屏) | land(横屏) API级别:v14 | v21 | v26 | v29 匹配规则:最精确 → 降级 → 默认

3.10 总结一下

res目录是Android资源管理的基石。记住几个要点:

  • mipmap放图标,drawable放其他图片,别搞混
  • values目录统一管理字符串、颜色、尺寸,方便后期维护
  • 资源限定符是适配利器,密度、语言、屏幕方向都能自动匹配
  • 限定符越多越精确,但也要考虑降级路径

我在多个项目里都坚持这套规范,团队协作效率明显提升。说白了,资源管理做得好,后期改需求时能省不少事。