Material You 设计

从 Android 12 开始,Material You 设计侧重于 Android OS 的表现力和流畅性,目标是帮助用户打造并拥有一种迎合其需求且可形成一个有机整体的使用体验。作为 Android 合作伙伴,我们建议您在以下领域将 Material You 设计整合到 Android 设备中:

  • 动态配色
  • 动画
  • 微件

动态配色

动态配色功能是 Material You 设计的核心,也是 Android 多年来一直秉持的策略(即,以独特的方式为用户提供更简单、更深入的定制体验)的重要组成部分。Material You:

  • 让用户和开发者可在任何 Android 设备中获得一致且丰富的个性化体验。

  • 让 Android OEM 有机会以一种与其硬件和品牌颜色、型号和外形相符的方式,继续对系统界面和第一方应用进行创新。

为了充分利用动态配色功能,请将 Android 12 Material You 颜色提取方案作为您向用户提供的软件的关键部分。在设备上,使用 AOSP 中的颜色提取逻辑,尤其是接受单一壁纸或主题源颜色并通过 65 种颜色 API 输出该颜色的逻辑。如需了解动态配色要求,请参阅使用动态配色。

完整的动态配色流程包括四个步骤,如下所示:

Material You 配色流程

图 1. Material You 动态配色流程

  1. 用户通过 OEM 选择器更改壁纸或主题。

  2. 用户选择下列其中一项:

    • 设备主题。选择此选项后,Android 会自动选择符合要求的单一源颜色。

    • 新壁纸 + 主题。选择此选项后,AOSP 逻辑会自动从所选壁纸中选择单一源颜色。

  3. 根据 AOSP 逻辑,AOSP 将单一源颜色扩展为 5 种色调调色板,每种调色板包含 13 个色调颜色变体,然后填充 65 个颜色属性。

  4. 应用界面使用 65 个颜色属性,这些属性在整个 Android 应用生态系统中保持一致。建议您为设备系统界面和 OEM 专属应用使用相同的调色板。

Android 12 补丁

如需获取壁纸颜色提取的端到端逻辑,并使设备能够以与生态系统保持一致的方式填充 65 色 API,请在 Android 12 实现中添加以下补丁:

在 ThemePicker 上指定自定义颜色

如果您使用的是 AOSP ThemePicker 应用,当同时满足以下两个条件时,WallpaperPicker 应用就会显示颜色部分:

  • frameworks/base/packages/SystemUI/res/values/flags.xml 中的 flag_monet 为 true。
  • 在 packages/apps/ThemePicker/res/values/override.xml 文件的 themes_stub_package 中定义了含有软件包名称的系统桩 APK。

桩 APK 的格式

您可以在 packages/apps/ThemePicker/themes 中找到此 APK 的示例版本。

该 APK 应仅包含相关资源,详细说明可用的基本颜色及其名称。

桩应在 res/xml 下包含采用以下格式的 XML 文件:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <array name="color_bundles">
        <item>color1</item>
        <item>color2</item>
        <item>color3</item>
        <item>color4</item>
    </array>

    <string name="bundle_name_color1">Blue</string>
    <string name="bundle_name_color2">Red</string>
    <string name="bundle_name_color3">Yellow</string>
    <string name="bundle_name_color4">Green</string>

</resources>

在此文件中,color_bundles 中的每个 item 都有一个独特的名称,只要下面的字符串命名为 bundle_name_item 即可。

每种颜色都应该有一个 bundle_name_item 字符串,并为每种颜色指定一个描述性名称。您可以通过将相应的已翻译字符串添加到 res/values-language code 目录来翻译这些字符串。

实际的颜色值可以位于相同的 XML 中,也可以位于具有以下格式的单独资源 XML 文件中:

<resources>
    <color name="color_primary_color1">#0000FF</color>
    <color name="color_secondary_color1">#0000FF</color>

    <color name="color_primary_color2">#ff0000</color>
    <color name="color_secondary_color2">#ff0000</color>

    <color name="color_primary_color3">#ffff00</color>
    <color name="color_secondary_color3">#ffff00</color>

    <color name="color_primary_color4">#00ff00</color>
    <color name="color_secondary_color4">#00ff00</color>
</resources>

颜色组合数组中的每一项都应有一个 color_primary_item 和 color_secondary_item 条目(且这两种颜色应是相同的颜色)。这些 color 条目的值是要在“基本颜色”部分显示的各种颜色的实际颜色代码。

第 1 步:打造用户主题体验

用户可通过主题选择器与新的 Material You 个性化功能互动,并可能会在颜色选项或预设之间进行选择。由于它适合您的产品和用户受众特征,因此您可以通过使用主题选择器或壁纸选择器为用户提供更丰富的个性化和颜色体验。

  • 在使用壁纸选择器时,壁纸颜色提取功能默认处于开启状态。不过,您可以对选择器进行一些自定义,以便为用户提供更多选项。

第 2 步:将壁纸颜色提取为源颜色

如需启用壁纸颜色提取功能,请择优挑选上面列出的 Android 12 补丁(在未来的 AOSP 版本中,此功能将默认处于启用状态)。触发壁纸提取功能的 AOSP 逻辑从 ThemeOverlayController#mOnColorsChangedListener 上的 frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java 开始,经由 WallpaperManager#onWallpaperColorsChanged。我们建议您使用未经修改的 AOSP 逻辑以确保一致的开发体验。

默认情况下,该逻辑会选择适合使用的最高频率颜色。为了利用通过算法返回的其他源颜色,并将这些颜色在主题选择器中呈现给用户,请使用 ColorScheme#getSeedColors(wallpaperColors: WallpaperColors)。

为了适合使用,源颜色(无论是从壁纸中提取还是由用户选择的预设)的 CAM16 色度值下限必须为 5;这样可确保源颜色在从单一颜色转换为 65 种色调颜色时不受轻微暗色调的影响,并且仍然能代表用户的选择。如需读取和修改 CAM16 中的颜色,请使用 Cam#fromInt 或 Cam#getInt。

使用非动态调色板对于不支持壁纸颜色提取的设备,您仍可通过执行以下操作来确保 Google 应用和支持动态配色的第三方应用拥有精美外观:

  • 使用默认的 Material 调色板,方法是在 frameworks/base/packages/SystemUI/res/values/flags.xml 中停用 flag_monet。
  • 确保用户仍可以使用预设主题选择器对其操作系统进行个性化设置。

第 3 步:将源颜色扩展到颜色 API

使用从上一步派生的单一源颜色,Android 会生成 5 种不同的色调调色板(accent 1-3、neutral 1-2),每种调色板包含 13 种颜色,每种颜色包含不同的亮度值(0 到 1000),总共有 65 种颜色。Android 12 补丁程序中提供的逻辑会正确实现此颜色扩展;下面提供的详细信息介绍了实现方式。

为保证开发者体验一致性,5 种色调调色板(accent1、accent2、accent3、neutral1、neutral2)及其对应的 13 种颜色必须基于单一源颜色,并且必须按如下所述对 CAM16 色度和色调值进行相应的更改:

  • system_accent1

    • 色度:对以 0、10、50 和 100 结尾的颜色变体使用“40”,否则使用“48”
    • 色调:与源颜色相同
  • system_accent2

    • 色度:使用“16”
    • 色调:与源颜色相同
  • system_accent3

    • 色度:使用“32”
    • 色调:正向旋转 60 度
  • system_neutral1

    • 色度:使用“4”
    • 色调:与源颜色相同
  • system_neutral2

    • 色度:使用“8”
    • 色调:与源颜色相同

CTS 包含用于验证亮度和色调 API 调用的测试。如需运行该工具,请使用 atest SystemPalette。

第 4 步:在应用和系统界面中使用动态配色

在设备上设置动态配色后,应用应遵循 Material 准则来利用这些颜色。Material 准则将于 2021 年 10 月 26 日之前在 material.io 上发布,供第三方应用采用。对于系统界面和第一方应用,我们强烈建议您在整个用户体验过程中集成动态配色,让其适合您的硬件和品牌,并帮助您区分设备。

如需了解一般动态配色指南,请参阅以下内容:

  • 对应用和系统界面中的前景元素使用强调色:

    @android:color/system_accent1_0 … 1000 // most-used foreground color group
    @android:color/system_accent2_0 … 1000 // alternate accent, used for surfaces
    @android:color/system_accent3_0 … 1000 // playful, analogous color
    
  • 对应用和系统界面中的背景元素使用中性颜色:

    @android:color/system_neutral1_0 … 1000 // most-used background color group
    @android:color/system_neutral2_0 … 1000 // used for higher-elevation surfaces
    

如需详细了解 Material You 如何映射颜色以及如何在 SysUI 中使用 API,请参阅其他资源。

第 5 步:在 AOSP WallpaperPicker 实现中添加动态配色选项

针对 Android 13 及更高版本进行构建

从 Android 13 开始,android.theme.customization.accent_color 已被废弃;并且添加了新属性 android.theme.customization.theme_style,以支持不同的颜色变体。目前,代码库中有四个变体,如下所示:

TONAL_SPOT = Default Material You theme since Android S.
VIBRANT = Theme where accent 2 and 3 are analogous to accent 1.
EXPRESSIVE = Highly chromatic theme.
SPRITZ = Desaturated theme, almost grayscale.

这些信息会发送到 Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES,如以下 JSON 所示:

{
    "android.theme.customization.system_palette":"B1611C",
    "android.theme.customization.theme_style":"EXPRESSIVE"
}

针对 Android 12 及更低版本进行构建

使用自定义主题选择器时,设备必须通过提供以下格式的 JSON 文件(其中 746BC1 是有效源颜色的示例)向 Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES 发送有效的源颜色:

{
      "android.theme.customization.system_palette":"746BC1",
      "android.theme.customization.accent_color":"746BC1"
}

执行此操作会跳过壁纸颜色提取(第 2 步),直接将提供的源颜色扩展为 65 个颜色属性(第 3 步)。

第 6 步:提交工单

除了系统集成之外,您还需要提交工单,并将您的品牌名称 (Build.MANUFACTURER) 告诉我们。由于大多数第三方应用使用 Material Components for Android 显示动态配色,因此我们使用硬编码的许可名单来了解哪些设备已集成动态配色调色板功能。

动画

流畅的运动让设备给人以现代的高端体验。为了建立和赢得开发者的信任,并让他们感到满意,滚动和涟漪是流畅运动的两个关键部分,需要具有一致的外观和风格。

在操作系统中使用滚动回弹效果

Android 12 包含响应更灵敏的动态滚动回弹动画(以视图拉伸形式呈现),当用户尝试滚动到列表边缘外时,系统就会显示这种效果。相关示例如下所示:

Material You 滚动回弹

图 2. Android 12 滚动效果,如“设置”中所示

为保证开发者体验一致性,请确保设备上的总体滚动效果与下方类似:

  • 在对 ActivityManager.isHighEndGfx() 返回 true 的设备上,滚动效果是屏幕的非线性拉伸(如上所示)。

  • 在性能较低的设备上,拉伸效果简化为线性拉伸(以减少系统的负载)。

在第一方应用中使用滚动

使用自定义视图时,您可能需要调整某些使用拉伸效果的应用和系统界面。

  • 如需支持拉伸滚动,请升级到最新的库:

    • androidx.recyclerview:recyclerview:1.3.0-alpha01(针对 RecyclerView)
    • androidx.core:core:1.7.0-alpha01(针对 NestedScrollView 和 EdgeEffectCompat)
    • androidx.viewpager:viewpager:1.1-alpha01(针对 ViewPager)
  • 对于使用 EdgeEffect 的自定义布局,请考虑以下用户体验变化:

    • 使用拉伸滚动回弹时,用户不应在系统拉伸布局时与布局内容进行互动。用户应该只操纵拉伸本身,例如,不能按下内容中的按钮。

    • 如果用户在 EdgeEffect 动画播放时轻触内容,他们应能看到该动画并被允许操纵拉伸。当前拉取值可从 EdgeEffectCompat.getDistance() 获得。

    • 如需操控拉取值并返回消耗的量,请使用 onPullDistance()。这样一来,当手指将内容拉伸至超过起始位置而又返回时,开发者便可以从拉伸顺畅地过渡到滚动。

    • 在使用嵌套滚动时,如果内容被拉伸,拉伸应在嵌套内容之前使用轻触动作,否则嵌套可能会在手指改变方向时滚动,而不是释放拉伸。

如需详细了解滚动,请参阅以动画方式显示滚动手势。

在操作系统中使用涟漪(轻触反馈)效果

Android 12 包含更柔和、更细微的轻触涟漪,可为用户提供点按反馈。

Material You 涟漪效果

图 3. Android 12 涟漪效果,填充动画更柔和

为实现开发者可预测性并提供出色的用户体验,请确保设备上的涟漪效果与上述示例类似。虽然您无需执行任何特定的集成步骤来支持涟漪效果,但应该在设备上测试这种效果,以检查您的实现中是否引入了任何意外的回归问题。

微件

widget 是 Android 设备的关键组件。Android 12 包含新的 API 以及所有 OEM 都应支持的 API 功能。

其他资源

SysUI 使用的颜色

(accent1 = A1、accent2 = A2、accent3 = A3、neutral1 = N1、neutral2 = N2)

Material You 使用的颜色

图 4. 系统界面中使用的动态配色

Material 库颜色属性更新

Material 将通过创建用于为特定视图提供颜色的颜色角色,在即将发布的版本中更新其主题属性。

颜色角色 Android 主题属性 浅色主题
动态配色
深色主题
动态配色
Primary colorPrimary system_accent1_600 system_accent1_200
On Primary colorOnPrimary system_accent1_0 system_accent1_800
次要 colorSecondary system_accent2_600 system_accent2_200
On Secondary colorOnSecondary system_accent2_0 system_accent2_800
错误 colorError 不适用 (red_600) 不适用 (red_200)
On Error colorOnError 不适用(白色) 不适用 (red_900)
背景 android:colorBackground system_neutral1_10 system_neutral1_900
On Background colorOnBackground system_neutral1_900 system_neutral1_100
Surface colorSurface system_neutral1_10 system_neutral1_900
On Surface colorOnSurface system_neutral1_900 system_neutral1_100

Material 将通过以下指针更新其状态属性:

颜色角色 Android 主题属性 浅色主题
动态配色
深色主题
动态配色
Primary 状态内容 colorPrimaryStateContent system_accent1_700 system_accent1_200
Primary 状态层 colorPrimaryStateLayer system_accent1_600 system_accent1_300
Secondary 状态内容 colorSecondaryStateContent system_accent2_700 system_accent2_200
Secondary 状态层 colorSecondaryStateLayer system_accent2_600 system_accent2_300
On Primary 状态内容 colorOnPrimaryStateContent system_accent1_0 system_accent1_800
On Primary 状态层 colorOnPrimaryStateLayer system_accent1_900 system_accent1_800
On Secondary 状态内容 colorOnSecondaryStateContent system_accent2_0 system_accent2_800
On Secondary 状态层 colorOnSecondaryStateLayer system_accent2_900 system_accent2_800
On Primary 容器状态内容 colorOnPrimaryContainerStateContent system_accent1_900 system_accent1_900
On Primary 容器状态层 colorOnPrimaryContainerStateLayer system_accent1_900 system_accent1_900
On Secondary 容器状态内容 colorOnSecondaryContainerStateContent system_accent2_900 system_accent2_900
On Secondary 容器状态层 colorOnSecondaryContainerStateLayer system_accent2_900 system_accent2_900
On Tertiary 容器状态内容 colorOnTertiaryContainerStateContent system_accent3_900 system_accent3_900
On Tertiary 容器状态层 colorOnTertiaryContainerStateLayer system_accent3_900 system_accent3_900
On Surface 状态内容 colorOnSurfaceStateContent system_neutral1_900 system_neutral1_100
On Surface 状态层 colorOnSurfaceStateLayer system_neutral1_900 system_neutral1_100
On Surface 变体状态内容 colorOnSurfaceVariantStateContent system_neutral2_700 system_neutral2_200
On Surface 变体状态层 colorOnSurfaceVariantStateLayer system_neutral2_700 system_neutral2_200
Error 状态内容 colorErrorStateContent red800 red200

常见问题解答

颜色提取

用户更换壁纸后,颜色提取会自动完成还是需要从某个位置触发?

在 Android 12 补丁中,壁纸颜色提取功能默认处于开启状态。

ThemeOverlayController.java 使用 ThemeOverlayController#mOnColorsChangedListener 和 WallpaperManager#onWallpaperColorsChanged 触发相关逻辑。

对于动态壁纸或视频壁纸,我们能否知道颜色提取功能何时从屏幕画面中获取颜色?某些用户可能需要最后一帧的颜色,因为该帧在大多数时间会显示。

当用户设置壁纸或屏幕重启(响应 WallpaperEngine#notifyColorsChanged)后,颜色提取就会触发。最后一次 WallpaperColors 事件(在动态壁纸中)会在用户关闭并再次开启屏幕后应用。

主题/壁纸选择器

如何使主题选择器能够显示多种源颜色以供用户选择,而不是只显示频率最高的颜色?有没有从提取逻辑中获取这些颜色的方法?

有。在主题选择器中,您可以使用 ColorScheme#getSeedColors(wallpaperColors: WallpaperColors)。

Pixel 中有一个名为“主题图标”的功能。你们共享的三个补丁中是否包含此功能?OEM 如何才能实现此功能?

不包含。“主题图标”目前为 Beta 版,未在 Android 12 中推出。

有没有办法在已启用颜色提取和选择功能的情况下使用 Google 壁纸应用?

有。您可以按照本页面前面所述的集成步骤,在最新版 Google 壁纸应用中实现这些功能。

如需了解详情,请与您的 TAM 联系。

Google 能不能共享该应用或源代码,以便 OEM 在其设置菜单中实现自己的动态配色预览版本(该版本与 Google 的壁纸选择器应用显示的预览部分外观相似)?

用于呈现预览的主要类为 WallpaperPicker2 和 Launcher3。

壁纸预览屏幕则为 WallpaperSectionController。

在更改颜色后,如何实现 Google 壁纸应用中所示的预览?

壁纸选择器应用需要启动器中包含 ContentProvider(基于 Launcher3 的启动器中都会包含)。预览由启动器中的 GridCustomizationsProvider 提供;它应在启动器的主 activity 的metadata中引用,以便壁纸和样式应用读取。前述所有项目均在 AOSP 的 Launcher3 中实现,并且可供 OEM 使用。