MaterialExpressiveTheme · AndroidX 源码指南
AAndroidX 源码指南
M3E 设计系统
ANDROIDX / COMPOSE / MATERIAL 3

MaterialExpressiveTheme

看清 Expressive 主题默认注入的颜色、运动、形状与排版,以及嵌套主题的行为。

它真正做了什么

首次进入 MaterialExpressiveTheme 时,源码把未传入的参数替换为以下默认值:

MaterialTheme(
    colorScheme = colorScheme ?: expressiveLightColorScheme(),
    motionScheme = motionScheme ?: MotionScheme.expressive(),
    shapes = shapes ?: Shapes(),
    typography = typography ?: Typography(),
    content = content,
)

所以 M3E 的主题入口不是只换颜色,它同时建立了 color、motion、shape、typography 四类默认值。

深色模式不是自动的

expressiveLightColorScheme() 的 KDoc 明确说它是 light scheme,并建议暗色模式使用 darkColorScheme()。官方 sample 也是自行判断系统主题:

val colorScheme =
    if (isSystemInDarkTheme()) darkColorScheme()
    else expressiveLightColorScheme()

MaterialExpressiveTheme(colorScheme = colorScheme) {
    AppContent()
}

也就是说,直接空参数调用 MaterialExpressiveTheme 时,源码默认落到 expressive 浅色配色;暗色切换仍由应用负责。

嵌套时为什么不重置

实现内部用 LocalUsingExpressiveTheme 判断是否已经处于 Expressive 主题。嵌套调用时,未提供的值继承当前 MaterialTheme,不会重新套一遍默认浅色主题。

推荐的应用主题壳

@Composable
fun ZMTheme(content: @Composable () -> Unit) {
    val colors =
        if (isSystemInDarkTheme()) darkColorScheme()
        else expressiveLightColorScheme()

    MaterialExpressiveTheme(
        colorScheme = colors,
        content = content,
    )
}

这只是源码可支持的最小写法。动态取色、品牌色、状态栏和可访问性对比度仍应按项目需求补充。

复制即用

一个完整可编译的主题壳,直接放进你的工程即可:

import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.material3.MaterialExpressiveTheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.expressiveLightColorScheme
import androidx.compose.runtime.Composable

@Composable
fun AppTheme(content: @Composable () -> Unit) {
    val colors =
        if (isSystemInDarkTheme()) darkColorScheme()
        else expressiveLightColorScheme()

    MaterialExpressiveTheme(
        colorScheme = colors,
        content = content,
    )
}

把上面的 AppTheme 包在 Activity 的 setContent 外层:

setContent {
    AppTheme {
        // 你的界面
    }
}

注意:空参数调用 MaterialExpressiveTheme 默认落到浅色配色;暗色切换需要像上面那样自行判断。