20、Material Design 3:Material You设计理念、主题与颜色系统、Material组件(BottomNavigation、TopAppBar、Card)、动态颜色适配

好,咱们今天聊点真正让Android应用“活起来”的东西——Material Design 3,也就是大家常说的Material You。

说实话,从Material Design 1.0到2.0,Google一直在打磨设计语言。但到了3.0,我觉得它才真正找到了灵魂。为什么?因为它不再是一套死板的规范,而是一套能“感知”用户个性的系统。

20.1 Material You:从“千人一面”到“千人千面”

Material You的核心思想,说白了就是:你的手机,应该像你

你想想看,以前我们做App,主题色是固定的。老板说用蓝色,全公司App就都是蓝色。用户拿到手里,跟隔壁张三的App一模一样。这合理吗?

Material You打破了这种僵局。它会从用户的壁纸中提取主色调,然后自动生成一套完整的配色方案。你的App,会随着用户壁纸的变化而自动换装。

我在项目中遇到过最典型的场景:用户反馈说“为什么我的App颜色跟别人不一样?”——这在以前是Bug,在Material You时代,这是Feature。

核心设计理念:
  • 个性化:颜色来自用户壁纸,每个人都是独一无二的
  • 自适应:组件、布局、动效都围绕颜色系统展开
  • 无障碍:颜色对比度、字体大小都经过优化,天生友好

20.2 主题与颜色系统:别再用ColorPrimary了

如果你还在用colorPrimarycolorAccent那套老写法,我建议你趁早改。Material You引入了一套全新的颜色系统,叫动态颜色

这套系统把颜色分成了五类角色:

颜色角色 作用 我常用的场景
Primary 主色,用于核心组件 TopAppBar背景、FAB按钮
On Primary 主色上的文字/图标色 TopAppBar上的标题文字
Secondary 辅助色,用于次要组件 底部导航栏选中状态
Surface 表面色,用于卡片、背景 Card的背景、Dialog背景
Error 错误色,用于提示 输入框校验失败时的边框

嗯,这里要注意:不要手动硬编码这些颜色。你应该通过主题属性来引用它们,比如?attr/colorPrimary。这样当用户壁纸变了,颜色会自动跟着变。

我曾经踩过一个坑:在自定义View里直接写了Color.BLUE,结果动态颜色一开,那个View死活不变色。后来改成ContextCompat.getColor(context, R.attr.colorPrimary)才搞定。

20.3 核心组件实战:BottomNavigation、TopAppBar、Card

光说不练假把式。咱们直接看代码,看看Material You组件怎么用。

20.3.1 BottomNavigation:底部导航栏

底部导航栏是App的“骨架”,用户靠它切换主要页面。Material 3的BottomNavigation支持动态颜色,选中项会自动使用colorPrimary

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottom_nav"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:menu="@menu/bottom_nav_menu"
    app:itemIconTint="@color/bottom_nav_color"
    app:itemTextColor="@color/bottom_nav_color"
    app:labelVisibilityMode="labeled" />

注意那个@color/bottom_nav_color,它应该是一个selector:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="true" android:color="?attr/colorPrimary" />
    <item android:color="?attr/colorOnSurfaceVariant" />
</selector>

这样选中时自动用主色,未选中时用浅色。用户换壁纸,颜色自动变。

20.3.2 TopAppBar:顶部应用栏

TopAppBar在Material 3里有了新变化。它支持大标题模式紧凑模式,滚动时还能自动切换。

<com.google.android.material.appbar.MaterialToolbar
    android:id="@+id/top_app_bar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    app:title="我的应用"
    app:titleTextColor="?attr/colorOnPrimary"
    app:navigationIcon="@drawable/ic_menu" />

我个人习惯把TopAppBar和CollapsingToolbarLayout配合使用,实现那种“图片折叠+标题浮现”的效果。但要注意:CollapsingToolbarLayout在Material 3里需要额外配置,否则动态颜色可能不生效。

20.3.3 Card:卡片组件

Card是Material Design的标志性组件。Material 3的Card默认带圆角和阴影,而且支持填充色轮廓色两种风格。

<com.google.android.material.card.MaterialCardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:cardBackgroundColor="?attr/colorSurface"
    app:strokeColor="?attr/colorOutline"
    app:strokeWidth="1dp"
    app:cardCornerRadius="12dp">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="16dp"
        android:text="这是一张卡片"
        android:textColor="?attr/colorOnSurface" />

</com.google.android.material.card.MaterialCardView>

这里有个小技巧:app:strokeColor设置为?attr/colorOutline,卡片会有一个淡淡的边框,视觉上更精致。如果去掉stroke,就是纯填充色卡片,适合内容较多的场景。

20.4 动态颜色适配:让App“读懂”用户壁纸

动态颜色是Material You的杀手锏。但实现起来并不复杂,核心就两步:

  1. 在主题中启用动态颜色
  2. 使用动态颜色属性

首先,在themes.xml中,把父主题改成Material 3的动态颜色主题:

<style name="Theme.MyApp" parent="Theme.Material3.DynamicColors.DayNight">
    <!-- 不需要手动定义颜色,系统会自动从壁纸提取 -->
</style>

然后,在布局和代码中,全部使用?attr/colorPrimary?attr/colorSurface这类属性。系统会自动映射到从壁纸提取的颜色上。

如果你需要手动获取动态颜色,可以用这个工具类:

val colors = DynamicColors.getColorScheme(context)
val primaryColor = colors.primary
val surfaceColor = colors.surface

我曾经在适配动态颜色时遇到一个问题:某些国产手机不支持动态颜色。嗯,这确实是个坑。解决方案是:先检测是否支持,如果不支持,就回退到预设的配色方案。

if (DynamicColors.isDynamicColorAvailable()) {
    DynamicColors.applyToActivityIfAvailable(activity)
} else {
    // 使用预设的Material 3颜色
    activity.setTheme(R.style.Theme_MyApp_Fallback)
}
避坑指南:
  • 动态颜色只在Android 12+上原生支持。低版本可以通过Material库的兼容层实现,但效果可能略有差异。
  • 不要在所有地方都用动态颜色。比如错误提示、警告信息,建议用固定颜色,确保用户能识别。
  • 测试时记得换不同的壁纸,看看颜色变化是否合理。有些壁纸提取出来的颜色可能对比度不够。

20.5 知识体系总览

为了帮你理清思路,我画了一张结构图。它展示了Material You从设计理念到具体实现的完整链路。

Material You 知识体系 Material You 设计理念 动态颜色系统(5大角色) Primary Secondary Surface Error On Colors Material 3 核心组件 BottomNavigation TopAppBar Card
我的建议:刚开始接触Material You时,不要试图一次性把所有组件都换成动态颜色。先挑一两个核心页面(比如首页、个人中心)做试点,跑通了再全面铺开。我在团队里就是这么推的,效果不错。

好了,关于Material Design 3的核心内容就这些。记住:设计规范是死的,用户是活的。Material You给了你一套强大的工具,但怎么用、用多少,最终还是取决于你对用户的理解。

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