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"
相关推荐
tangweiguo030519871 天前
Android Compose 权限申请完整指南
compose
tangweiguo030519876 天前
androd的XML页面 跳转 Compose Activity 卡顿问题
compose
tangweiguo030519876 天前
iOS 风格弹框组件集 (Compose版)
compose
tangweiguo030519877 天前
Android Compose 中获取和使用 Context 的完整指南
android·compose
tangweiguo030519879 天前
Jetpack Compose 自定义组件完全指南
compose
tangweiguo0305198710 天前
打破界限:Android XML与Jetpack Compose深度互操作指南
android·kotlin·compose
wavky1 个月前
零经验选手,Compose 一天开发一款小游戏!
compose
亚林瓜子1 个月前
Minio安装(Docker Compose方式)
运维·docker·容器·minio·compose
氦客3 个月前
Android Compose 显示底部对话框 (ModalBottomSheet),实现类似BottomSheetDialog的效果
android·dialog·ui·compose·modal·bottomsheet·底部对话框