Material You 设计

从 Android 12 开始,Material You 设计侧重于 Android 操作系统中的表现力和流动性,目标是帮助用户创建和拥有根据自身需求量身定制的单一、有凝聚力的体验。作为 Android 合作伙伴,我们鼓励您在 Android 设备中融入 Material You 设计,具体体现在以下方面:

  • 动态颜色
  • 动画效果
  • 小部件

动态颜色

动态颜色是 Material You 设计的核心,也是 Android 多年战略的关键部分,旨在以其他设备无法实现的方式,为用户带来更简单、更深入的自定义功能。Material You 提供:

  • 为用户和开发者提供一致且丰富的个性化故事,可在任何 Android 设备中使用。

  • 让 Android OEM 有机会继续创新系统 UI 和第一方应用,使其与其硬件和品牌颜色、制造商和外形保持一致。

要充分利用动态颜色,请使用 Android 12 Material You 颜色提取方案,将其作为您向用户提供的软件的关键组成部分。在设备上,使用 AOSP 中的颜色提取逻辑,尤其是从单一壁纸或主题源颜色输入并通过 65 个颜色 API 输出的逻辑。有关动态颜色要求,请参阅使用动态颜色

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

Material You Color Flow

图 1. Material You 动态颜色流程

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

  2. 用户选择以下选项之一:

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

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

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

  4. 应用 UI 以在整个 Android 应用生态系统中保持一致的方式使用 65 个颜色属性。我们鼓励您为设备系统 UI 和 OEM 专用应用使用相同的调色板。

Android 12 补丁

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

在 ThemePicker 上指定自定义颜色

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

  • frameworks/base/packages/SystemUI/res/values/flags.xml 中的 flag_monettrue
  • packages/apps/ThemePicker/res/values/override.xml 文件的 themes_stub_package 中定义了带有包名称的系统 APK。

桩 APK 格式

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

此 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 逻辑从 frameworks/base/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java 中的 ThemeOverlayController#mOnColorsChangedListener 开始,通过 WallpaperManager#onWallpaperColorsChanged 的方式。我们建议使用未修改的 AOSP 逻辑,以确保一致的开发体验。

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

为了适合使用,源颜色(无论是从壁纸提取还是用户选择的预设)必须具有至少 5 的 CAM16 色度值;这确保了源颜色在从单色转换为 65 种色调的颜色时不会受到细微暗色调的影响,并保持用户选择的代表性。要在 CAM16 中读取和修改颜色,请使用 Cam#fromIntCam#getInt

使用非动态调色板 对于不支持壁纸颜色提取的设备,您仍然可以通过执行以下操作来确保支持动态颜色的 Google 应用和第三方应用看起来很棒

  • 通过禁用 frameworks/base/packages/SystemUI/res/values/flags.xml 中的 flag_monet 来使用默认 Material 调色板。
  • 确保用户仍然可以使用预设主题选择器来个性化他们的操作系统。

步骤 3:将源颜色扩展为颜色 API

使用从上一步导出的单个源颜色,Android 生成 5 个独特的色调调色板(强调色 1-3,中性色 1-2),每个调色板包含 13 种颜色,每种颜色包含不同的亮度值(0 到 1000),总共 65 种颜色。Android 12 补丁 中提供的逻辑正确地实现了这种颜色扩展;下面提供的详细信息描述了实现方式。

为了开发人员的一致性,5 个色调调色板(accent1、accent2、accent3、neutral1、neutral2)及其对应的 13 种颜色必须基于具有以下 CAM16 色度和色相值更改的单个源颜色,如下所示

CTS 包括用于验证亮度和色相 API 调用的测试。要运行,请使用 atest SystemPalette

步骤 4:在应用和 System UI 中使用动态颜色

在设备上设置动态颜色后,应用会遵循 Material 指南来使用这些颜色。Material 指南将于 2021 年 10 月 26 日在 material.io 上发布,供第三方应用采用。对于 System UI 和第一方应用,我们强烈建议在整个用户体验中集成动态颜色,使其与您的硬件和品牌相符,并帮助您区分您的设备。

有关一般动态颜色指南,请参阅以下内容

  • 在应用和 System UI 中,对前景色元素使用强调色

    @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
    
  • 在应用和 System UI 中,对背景色元素使用中性色

    @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 Overscroll

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

为了开发人员的一致性,请确保您的设备上的整体过度滚动效果与以下效果相似

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

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

在第一方应用中使用过度滚动

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

  • 要支持拉伸过度滚动,请升级到最新的库

    • RecyclerViewandroidx.recyclerview:recyclerview:1.3.0-alpha01
    • NestedScrollViewEdgeEffectCompatandroidx.core:core:1.7.0-alpha01
    • ViewPagerandroidx.viewpager:viewpager:1.1-alpha01
  • 对于使用 EdgeEffect 的自定义布局,请考虑以下 UX 更改

    • 使用拉伸过度滚动时,用户不应在布局拉伸时与其内容进行交互。用户应仅操作拉伸本身,而不能例如按下内容中的按钮。

    • 当用户在 EdgeEffect 动画发生时触摸内容时,他们应捕获动画并被允许操作拉伸。当前拉动值可从 EdgeEffectCompat.getDistance() 获得。

    • 要操作拉动值并返回消耗的量,请使用 onPullDistance()。这允许开发人员在手指将内容拉伸超出起始位置时,从拉伸平滑过渡到滚动。

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

有关过度滚动的详细信息,请参阅动画滚动手势

在您的操作系统中使用波纹(触摸反馈)

Android 12 包括更柔和、更微妙的触摸波纹,以便在点击按下时向用户提供反馈。

Material You Ripple

图 3. Android 12 波纹效果,具有更柔和的填充动画

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

小部件

小部件是 Android 设备的关键组件。Android 12 包括所有 OEM 都应支持的新 API 和 API 功能。

其他资源

SysUI 颜色使用

(强调色 1 = A1,强调色 2 = A2,强调色 3 = A3,中性色 1 = N1,中性色 2 = N2)

Material You Color Use

图 4. System UI 中的动态颜色使用

Material 库颜色属性更新

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

颜色角色 Android 主题属性 浅色主题
动态颜色
深色主题
动态颜色
原色 colorPrimary system_accent1_600 system_accent1_200
在原色之上 colorOnPrimary system_accent1_0 system_accent1_800
辅助色 colorSecondary system_accent2_600 system_accent2_200
在辅助色之上 colorOnSecondary system_accent2_0 system_accent2_800
错误色 colorError N/A (red_600) N/A (red_200)
在错误色之上 colorOnError N/A (white) N/A (red_900)
背景色 android:colorBackground system_neutral1_10 system_neutral1_900
在背景色之上 colorOnBackground system_neutral1_900 system_neutral1_100
表面色 colorSurface system_neutral1_10 system_neutral1_900
在表面色之上 colorOnSurface system_neutral1_900 system_neutral1_100

Material 将使用以下指针更新其状态属性

颜色角色 Android 主题属性 浅色主题
动态颜色
深色主题
动态颜色
原色状态内容 colorPrimaryStateContent system_accent1_700 system_accent1_200
原色状态层 colorPrimaryStateLayer system_accent1_600 system_accent1_300
辅助色状态内容 colorSecondaryStateContent system_accent2_700 system_accent2_200
辅助色状态层 colorSecondaryStateLayer system_accent2_600 system_accent2_300
在原色状态内容之上 colorOnPrimaryStateContent system_accent1_0 system_accent1_800
在原色状态层之上 colorOnPrimaryStateLayer system_accent1_900 system_accent1_800
在辅助色状态内容之上 colorOnSecondaryStateContent system_accent2_0 system_accent2_800
在辅助色状态层之上 colorOnSecondaryStateLayer system_accent2_900 system_accent2_800
在原色容器状态内容之上 colorOnPrimaryContainerStateContent system_accent1_900 system_accent1_900
在原色容器状态层之上 colorOnPrimaryContainerStateLayer system_accent1_900 system_accent1_900
在辅助色容器状态内容之上 colorOnSecondaryContainerStateContent system_accent2_900 system_accent2_900
在辅助色容器状态层之上 colorOnSecondaryContainerStateLayer system_accent2_900 system_accent2_900
在三次色容器状态内容之上 colorOnTertiaryContainerStateContent system_accent3_900 system_accent3_900
在三次色容器状态层之上 colorOnTertiaryContainerStateLayer system_accent3_900 system_accent3_900
在表面色状态内容之上 colorOnSurfaceStateContent system_neutral1_900 system_neutral1_100
在表面色状态层之上 colorOnSurfaceStateLayer system_neutral1_900 system_neutral1_100
在表面变体状态内容之上 colorOnSurfaceVariantStateContent system_neutral2_700 system_neutral2_200
在表面变体状态层之上 colorOnSurfaceVariantStateLayer system_neutral2_700 system_neutral2_200
错误色状态内容 colorErrorStateContent red800 red200

常见问题解答

颜色提取

用户更改壁纸后,颜色提取是自动完成还是需要从某处触发?

使用 Android 12 补丁后,壁纸颜色提取默认开启

ThemeOverlayController.java 使用 ThemeOverlayController#mOnColorsChangedListenerWallpaperManager#onWallpaperColorsChanged 触发逻辑。

对于动态壁纸视频壁纸,我们是否可以知道颜色提取何时从屏幕上取色?有些用户可能希望从最后一帧获取颜色,因为它显示的时间最长。

颜色提取在用户设置壁纸或屏幕电源循环后(响应 WallpaperEngine#notifyColorsChanged)触发。最后一个 WallpaperColors 事件(来自动态壁纸)在用户关闭屏幕并重新打开屏幕后应用。

主题/壁纸选择器

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

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

Pixel 上有一个名为主题图标的功能。它是否包含在您共享的三个补丁中?OEM 如何实现它?

否。主题图标处于 Beta 版,在 Android 12 中不可用。

有没有办法将 Google 壁纸应用与启用的颜色提取和选择功能一起使用?

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

请联系您的 TAM 了解更多详情。

Google 能否分享应用或源代码,以便 OEM 可以在其设置菜单上实现自己的动态颜色预览版本,该版本看起来类似于 Google 壁纸选择器应用上显示的预览部分?

渲染预览的主要类是 WallpaperPicker2Launcher3

壁纸预览屏幕是 WallpaperSectionController

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

壁纸选择器应用期望 Launcher 提供 ContentProvider(基于 Launcher3 的启动器具有它)。预览由 Launcher 中的 GridCustomizationsProvider 提供,应在 Launcher 主 Activity 的 metadata 中引用,以便壁纸和样式应用可以读取它。所有这些都在 AOSP 的 Launcher3 中实现,OEM 可以使用。