Android Material Design 3 主题配色终极指南:XML 与 Compose 全解析

最小必要颜色配置

xml 复制代码
<!-- res/values/themes.xml -->
<style name="Theme.MyApp" parent="Theme.Material3.DayNight">
    <!-- 基础三原色 -->
    <item name="colorPrimary">@color/purple_500</item>
    <item name="colorSecondary">@color/teal_200</item>
    <item name="colorTertiary">@color/orange_200</item>
    
    <!-- 背景+文字 -->
    <item name="colorSurface">@color/white</item>
    <item name="colorOnSurface">@color/black</item>
</style>

对应效果

  • 按钮/导航栏:紫色
  • 开关/复选框:水绿色
  • 悬浮按钮:橙色容器
  • 背景:白色
  • 文字:黑色

基础控件颜色映射

控件 使用的颜色属性
按钮 colorPrimary + colorOnPrimary
开关 colorSecondary
卡片 colorSurface
文本 colorOnSurface

XML 和 Compose 双版本的完整代码注释,按功能模块划分:


一、基础颜色配置

1. XML 版本 (res/values/themes.xml)
xml 复制代码
<!-- 主品牌色:用于FAB、主要按钮等 -->
<item name="colorPrimary">@color/purple_500</item>

<!-- 主色上的内容色:确保与主色有足够对比度 -->
<item name="colorOnPrimary">@color/white</item>

<!-- 次要品牌色:用于开关、单选按钮等 -->
<item name="colorSecondary">@color/teal_200</item>

<!-- 背景系统:页面基础背景 -->
<item name="colorSurface">@color/white</item>

<!-- 背景上的内容色:普通文本颜色 -->
<item name="colorOnSurface">@color/black</item>

<!-- 错误色:错误提示文本/边框 -->
<item name="colorError">@color/red_500</item>
2. Compose 版本 (Theme.kt)
kotlin 复制代码
val LightColorScheme = lightColorScheme(
    // 主色容器:FAB背景色
    primary = Color(0xFF6750A4),
    // 主色上的内容:FAB图标颜色
    onPrimary = Color(0xFFFFFFFF),
    // 次要色:Switch滑块颜色
    secondary = Color(0xFF958DA5),
    // 背景色:页面底色
    surface = Color(0xFFFFFBFE),
    // 背景上的内容:普通文本
    onSurface = Color(0xFF1C1B1F),
    // 错误色
    error = Color(0xFFB3261E)
)

二、控件颜色映射

1. 按钮 (Button)
xml 复制代码
<!-- XML版 -->
<Button
    android:backgroundTint="?attr/colorPrimary"
    android:textColor="?attr/colorOnPrimary"/>
kotlin 复制代码
// Compose版
Button(
    colors = ButtonDefaults.buttonColors(
        containerColor = MaterialTheme.colorScheme.primary,
        contentColor = MaterialTheme.colorScheme.onPrimary,
        // 禁用状态颜色(自动降低透明度)
        disabledContainerColor = MaterialTheme.colorScheme.surfaceVariant,
        disabledContentColor = MaterialTheme.colorScheme.onSurfaceVariant
    )
) { Text("按钮") }
2. 卡片 (Card)
xml 复制代码
<!-- XML版 -->
<androidx.cardview.widget.CardView
    app:cardBackgroundColor="?attr/colorSurface"
    app:strokeColor="?attr/colorOutline">
kotlin 复制代码
// Compose版
Card(
    colors = CardDefaults.cardColors(
        containerColor = MaterialTheme.colorScheme.surface,
        contentColor = MaterialTheme.colorScheme.onSurface
    ),
    border = CardDefaults.outlinedCardBorder(
        borderColor = MaterialTheme.colorScheme.outline
    )
) { /* 内容 */ }
3. 开关 (Switch)
xml 复制代码
<!-- XML版 -->
<Switch
    android:trackTint="?attr/colorSecondaryContainer"
    android:thumbTint="?attr/colorOnSecondary"/>
kotlin 复制代码
// Compose版
Switch(
    colors = SwitchDefaults.colors(
        checkedThumbColor = MaterialTheme.colorScheme.onSecondary,
        checkedTrackColor = MaterialTheme.colorScheme.secondary,
        uncheckedThumbColor = MaterialTheme.colorScheme.surfaceVariant,
        uncheckedTrackColor = MaterialTheme.colorScheme.onSurfaceVariant
    )
)

三、深色模式适配

1. XML 配置 (res/values-night/themes.xml)
xml 复制代码
<style name="Theme.MyApp" parent="Theme.Material3.DayNight">
    <!-- 深色背景 -->
    <item name="colorSurface">@color/dark_surface</item>
    <!-- 深色文字 -->
    <item name="colorOnSurface">@color/dark_on_surface</item>
    <!-- 深色轮廓线 -->
    <item name="colorOutline">@color/dark_outline</item>
</style>
2. Compose 配置
kotlin 复制代码
val DarkColorScheme = darkColorScheme(
    surface = Color(0xFF1C1B1F),
    onSurface = Color(0xFFE6E1E5),
    outline = Color(0xFF938F99)
)

@Composable
fun MyAppTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    content: @Composable () -> Unit
) {
    val colorScheme = if (darkTheme) DarkColorScheme else LightColorScheme
    MaterialTheme(
        colorScheme = colorScheme,
        content = content
    )
}

四、动态颜色(Android 12+)

1. XML 配置
xml 复制代码
<!-- res/values-v31/themes.xml -->
<style name="Theme.MyApp" parent="Theme.Material3.DayNight.DynamicColors">
    <item name="android:dynamicColorThemeOverlay">
        @style/ThemeOverlay.App.Dynamic
    </item>
</style>
2. Compose 集成
kotlin 复制代码
@Composable
fun DynamicColorWrapper(content: @Composable () -> Unit) {
    val context = LocalContext.current
    val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
    
    if (dynamicColor) {
        DynamicColors.rememberDynamicColors().apply {
            if (isDynamicColorAvailable) {
                LaunchedEffect(key1 = colorScheme) {
                    // 动态颜色应用后的回调
                }
            }
        }
    }
    content()
}

五、完整主题构建示例

XML 全量配置
xml 复制代码
<style name="Theme.MyApp" parent="Theme.Material3.DayNight">
    <!-- 主色系 -->
    <item name="colorPrimary">@color/primary_500</item>
    <item name="colorOnPrimary">@color/white</item>
    <item name="colorPrimaryContainer">@color/primary_100</item>
    
    <!-- 文字系统 -->
    <item name="textColorPrimary">?attr/colorOnSurface</item>
    <item name="textColorSecondary">?attr/colorOnSurfaceVariant</item>
    
    <!-- 控件状态 -->
    <item name="colorControlNormal">?attr/colorOnSurface</item>
    <item name="colorControlActivated">?attr/colorPrimary</item>
</style>
Compose 全量主题
kotlin 复制代码
private val Typography = Typography(
    // 标题文字样式
    titleLarge = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Bold,
        fontSize = 22.sp,
        color = MaterialTheme.colorScheme.onSurface
    ),
    // 正文样式
    bodyMedium = TextStyle(
        fontFamily = FontFamily.Default,
        fontWeight = FontWeight.Normal,
        fontSize = 16.sp,
        color = MaterialTheme.colorScheme.onSurface
    )
)

@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        colorScheme = if (isDarkTheme()) DarkColorScheme else LightColorScheme,
        typography = Typography,
        shapes = Shapes(),
        content = content
    )
}

关键注意事项

  1. XML 与 Compose 混用场景

    kotlin 复制代码
    // 在Compose中使用XML定义的颜色
    val color = Color(ContextCompat.getColor(context, R.color.primary_500))
  2. 颜色覆盖优先级

    复制代码
    控件直接设置 > 样式定义 > 主题默认值
  3. 调试命令

    bash 复制代码
    # 查看当前主题属性
    adb shell dumpsys activity top | grep "mTheme"
相关推荐
至乐活着10 天前
Docker Compose多服务编排实战:从零搭建Node.js+MySQL+Redis全栈应用
docker·微服务·devops·容器编排·compose
le16161621 天前
Android Compose——尺寸修饰符的调用顺序构成的不同尺寸约束效果
android·compose·modifier
le16161622 天前
Android Compose Modifier修饰符
android·compose·modifier
小书房22 天前
Android UI为什么由XML转向Compose
xml·ui·compose·声明式ui
le16161623 天前
Android Compose基础布局——从传统XML的视角切入了解
xml·compose
赏金术士1 个月前
企业级 Jetpack Compose 项目(入门版)最佳结构
android·kotlin·compose
Jomurphys1 个月前
Compose 调用 - 液态玻璃 Backdrop
android·compose
氦客1 个月前
Android Compose 图层的合成 : BlendMode
android·compose·jetpack·layer·blendmode·graphics·图层的合成
赏金术士1 个月前
第六章:UI组件与Material3主题
android·ui·kotlin·compose
赏金术士1 个月前
Jetpack Compose 底部导航实战教程(完整版)
android·kotlin·compose