18、资源管理:字符串、颜色、尺寸、Drawable资源、主题属性引用

资源管理这件事,说实话,是很多初学者容易忽略的「基本功」。我记得刚入行那会儿,觉得把字符串直接写在代码里多方便啊,何必多此一举去建个xml文件?直到后来接手一个项目,需要做多语言适配……嗯,那场面,简直是一场灾难。

今天我们就来系统地聊聊Android资源管理。说白了,就是把那些「可能会变」的东西,从代码里抽出来,放到专门的资源文件里。这样不仅好维护,还能轻松适配不同设备、不同语言。

18.1 字符串资源:不只是文本

字符串资源是最常用的。在res/values/strings.xml里定义,然后在代码或布局中引用。

<!-- res/values/strings.xml -->
<resources>
    <string name="app_name">我的应用</string>
    <string name="welcome_message">欢迎使用本应用!</string>
    <string name="login_hint">请输入用户名和密码</string>
</resources>

在Compose中引用字符串资源,用stringResource()函数:

@Composable
fun Greeting() {
    Text(
        text = stringResource(R.string.welcome_message)
    )
}
小技巧:字符串可以带占位符。比如「你好,%s」,这样就能动态插入用户名。我在项目中经常用这种方式做提示信息,比拼接字符串优雅多了。
<string name="greeting_user">你好,%s!</string>

// 使用时
Text(text = stringResource(R.string.greeting_user, "小明"))

18.2 颜色资源:统一视觉风格

颜色定义在res/values/colors.xml里。一个项目如果没有统一的颜色管理,后期改主题色会让你怀疑人生。

<!-- res/values/colors.xml -->
<resources>
    <color name="primary">#FF6200EE</color>
    <color name="primary_variant">#FF3700B3</color>
    <color name="secondary">#FF03DAC5</color>
    <color name="background">#FFFFFFFF</color>
    <color name="on_primary">#FFFFFFFF</color>
</resources>

在Compose中,用colorResource()来获取:

@Composable
fun ColoredText() {
    Text(
        text = "这是主题色",
        color = colorResource(R.color.primary)
    )
}
注意:Compose有自己的Color系统,比如MaterialTheme.colors.primary。如果你在用Material Design组件,建议优先用主题颜色,而不是硬编码颜色资源。我曾经在一个项目里混用了两种方式,结果主题切换时颜色乱成一团……

18.3 尺寸资源:适配不同屏幕

尺寸资源放在res/values/dimens.xml里。为什么要用尺寸资源?因为不同屏幕密度下,同样的dp值看起来大小不一样。

<!-- res/values/dimens.xml -->
<resources>
    <dimen name="padding_small">8dp</dimen>
    <dimen name="padding_medium">16dp</dimen>
    <dimen name="padding_large">24dp</dimen>
    <dimen name="text_size_title">20sp</dimen>
    <dimen name="text_size_body">14sp</dimen>
</resources>

在Compose中,用dimensionResource()

@Composable
fun SizedBox() {
    Spacer(
        modifier = Modifier
            .height(dimensionResource(R.dimen.padding_medium))
            .fillMaxWidth()
    )
}
核心要点:尺寸资源最适合用在「需要统一管理间距、字号」的场景。如果你只是某个组件独有的尺寸,直接写dp值也没问题。我个人习惯是:全局通用的尺寸放资源文件,局部特有的直接写。

18.4 Drawable资源:图片与形状

Drawable资源包括图片(png、jpg、webp)和矢量图(Vector Drawable)。放在res/drawable/目录下。

矢量图在Android中特别推荐使用,因为它缩放不失真,文件还小。用Vector Asset工具可以快速导入Material Icons或SVG文件。

<!-- res/drawable/ic_arrow_back.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24">
    <path
        android:fillColor="#FF000000"
        android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
</vector>

在Compose中加载图片:

@Composable
fun BackIcon() {
    Image(
        painter = painterResource(R.drawable.ic_arrow_back),
        contentDescription = "返回"
    )
}
避坑指南:我曾经把一张大图直接放在drawable-mdpi里,结果在hdpi设备上显示模糊,在xxhdpi设备上又内存爆了。后来学乖了:矢量图用Vector Drawable,位图用WebP格式,并且放在正确的密度目录下。

18.5 主题属性引用:动态换肤的利器

主题属性引用,说白了就是「引用当前主题里定义的颜色或样式」。这样当主题切换时,引用的值会自动变化。

在XML布局中,用?attr/语法:

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="主题色文字"
    android:textColor="?attr/colorPrimary" />

在Compose中,通过MaterialTheme.colors来访问:

@Composable
fun ThemedText() {
    Text(
        text = "主题色文字",
        color = MaterialTheme.colors.primary
    )
}

如果你想自定义主题属性,可以这样:

<!-- res/values/attrs.xml -->
<resources>
    <attr name="customBackgroundColor" format="color" />
</resources>

然后在主题中赋值:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight">
    <item name="customBackgroundColor">#FFE0E0E0</item>
</style>
注意:主题属性引用在Compose中不如在XML中那么直接。Compose更推荐用MaterialTheme的扩展属性。如果你需要自定义主题属性,建议用Compose的CompositionLocal来实现。

18.6 知识体系总览

下面这张图,帮你理清资源管理的整体脉络:

Android资源管理 字符串资源 strings.xml 颜色资源 colors.xml 尺寸资源 dimens.xml Drawable资源 drawable/ 主题属性引用 ?attr/ 或 MaterialTheme 核心原则:将可变值抽离到资源文件中

18.7 实战建议

说了这么多,总结几条我自己的经验:

  • 字符串一定要用资源文件——哪怕你现在只做中文版。多语言适配时你会感谢自己的。
  • 颜色统一管理——定义好主色、辅色、背景色、文字色,别到处写#FFxxxx。
  • 尺寸用dp和sp——dp用于布局,sp用于文字。别混用。
  • 图片优先用Vector Drawable——除非图片太复杂,否则矢量图是更好的选择。
  • 主题属性引用是高级玩法——如果你要做深色模式或换肤,这是必经之路。
一句话总结:资源管理不是「把东西放到xml里」这么简单,它是一种设计思想——把变化的部分和不变的部分分离。做到这一点,你的代码会更好维护、更易扩展。

好了,资源管理就聊到这里。记住:好的资源管理习惯,能让你少加很多班。


公众号:蓝海资料掘金营,微信deep3321