向应用添加动态配色

1. 准备工作

在此 Codelab 中,您将更新起始应用(小费计算器应用),以使用 Material Design 3 中的新功能,从而根据用户的壁纸为应用的界面动态设置主题。以下是应用了动态配色的应用的几张屏幕截图。您还将了解其他一些可让您控制颜色应用方式的场景。

前提条件

开发者应

  • 熟悉 Android 中的基本主题概念
  • 擅长修改应用主题

学习内容

  • 如何区分现有的 Material 组件和 Material 3 主题
  • 如何将主题更新为 Material 3
  • 如何使用我们的工具创建主题并应用这些主题
  • 主题属性之间的关系

所需条件

2. 起始应用概览

Tip Time 应用是一款小费计算器应用,提供自定义小费的选项。它是我们的《使用 Kotlin 进行 Android 开发的基础知识》培训课程中的示例应用之一。

59906a9f19d6b804

3. 更新 Gradle 依赖项

在我们更新实际主题并应用动态配色之前,您需要在应用的 build.gradle 文件中进行一些更改。

在“dependencies”部分,确保 Material 库为 1.5.0-alpha04 或更高版本:

dependencies {
    // ...
    implementation 'com.google.android.material:material:<version>'
}

在 android 部分,更改 compileSdkVersion 和 targetSdkVersion

到 31 或更高版本:

android {
    compileSdkVersion 31
    // ...

    defaultConfig {
        // ...
        targetSdkVersion 31
    }
}

这些说明假定应用具有相对较新的依赖项。对于尚未使用 Material 或更低版本的应用,请查看适用于 Android 的 Material Design 组件使用入门文档中的说明。

无论您在何处创建主题,请将对 Theme.MaterialComponents.* 的引用更改为 Theme.Material3.*。某些样式在 Material3 命名空间中还没有新样式,但当父主题更新为 Theme.Material3.* 后,大多数组件仍会继承新样式。我们可以看到,按钮现在采用了新的圆角主题。

在下面的主题文件中,唯一发生变化的是父主题。我们稍后会完全替换此主题。一些颜色属性已作废,我们创建的一些自定义样式现在是 Material3 中的标准样式,但我们希望您将

themes.xml

<style name="Theme.TipTime" parent="Theme.Material3.Light">
   <!-- Primary brand color. -->
   <item name="colorPrimary">@color/green</item>
   <item name="colorPrimaryVariant">@color/green_dark</item>
   <item name="colorOnPrimary">@color/white</item>
   <!-- Secondary brand color. -->
   <item name="colorSecondary">@color/blue</item>
   <item name="colorSecondaryVariant">@color/blue_dark</item>
   <item name="colorOnSecondary">@color/black</item>
   <!-- Status bar color. -->
   <item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
   <!-- For text input fields -->
   <item name="textInputStyle">@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
   <!-- For radio buttons -->
   <item name="radioButtonStyle">@style/Widget.TipTime.CompoundButton.RadioButton</item>
   <!-- For switches -->
   <item name="switchStyle">@style/Widget.TipTime.CompoundButton.Switch</item>
</style>

f91e2acbac7cd469.png

4. 了解颜色主题和颜色角色

Material 3 颜色系统以组织有序的方式将颜色应用到界面。Theme.AppCompat 中的许多属性仍在使用。不过,我们在 Theme.MaterialComponents.* 中添加了更多的属性,在 Theme.Material3.* 中添加了更多的属性,因此请务必检查应用的所有屏幕,以确保没有从基本主题中渗漏未实现的属性。

了解颜色角色

Material 3 主题中有超过 20 个与颜色相关的属性。乍一看,这似乎有点让人望而生畏,但实际上会有几个关键的颜色与 4-5 种相同的颜色角色相结合,从而形成衍生颜色。

这些颜色组包括:

  • Primary(主色),即应用的主色
  • secondary,应用的次要颜色
  • 第三色,用于辅助主色和辅色的第三种颜色
  • 错误,用于错误文本和对话框
  • 背景
  • Surface、SurfaceVariant、Surface Inverse

主要、次要、第三和错误角色如下:

<基本颜色>

基本颜色

on<基准颜色>

在基本颜色上显示的图标和文本的颜色

<base color>容器

派生自基础颜色、颜色,用于按钮、对话框等

on<base color>容器

容器中图标和文字的颜色

例如,Material 3 中采用默认样式的悬浮操作按钮使用 Primary 作为其基本颜色,因此它使用 primaryContainer 作为按钮的背景颜色,使用 onPrimaryContainer 作为其内容。

手动自定义主题时,您至少应验证您更改的每个基础颜色的 on<base color> 属性是否仍然清晰易读。

最佳实践是同时调整一个颜色组中的所有角色,以确保从基础到您的应用没有任何伪影。

背景和 Surface 基础颜色通常有两个角色:基础颜色本身和 on<base color>(用于呈现在其上的图标或文本)。

5. 使用 Material Theme Builder 创建 Material 3 主题

借助 Material Theme Builder,您可以轻松构建自定义配色方案,使用其内置的代码导出功能迁移到 M3 颜色系统,并充分利用动态配色功能。了解详情 material.io/material-theme-builder

Tip Time 应用主题包含多种组件样式,但大多数样式都是 Material 3 主题中的默认样式。我们只需要关注两个主要颜色,即主要颜色和次要颜色。

这分别对应于绿色主要颜色 (#1B5E20) 和蓝色次要颜色 (#0288D1)。

您可以将这些颜色输入到 Material 主题构建器中,并导出完整的主题(假设在其他地方提供指向完整概览的链接)。

请注意,您输入的颜色可能会改变色调,以符合颜色生成算法,并确保颜色互补且易读。

以下是您输入自定义颜色时生成的值的子集。

7f6c5a33f5233811

6. 使用 Material Theme Builder 导出文件

导出归档包含 values 和 values-night/ 目录,它们都有自己的 topics.xml 文件,分别对应于浅色和深色主题。所有颜色均在 values/colors.xml 中定义。

f66a64db2989a260.png

这些文件可以按原样复制,但您必须更改主题名称 AndroidManifest.xml 或主题文件,以便相互匹配。工具的默认名称是 AppTheme。

重启应用,它看起来几乎完全一样。一个值得注意的变化是 Switch 和 RadioButtons,它们的选定状态现在以主要颜色与次要颜色的色调为主题。在较大的应用中,您可能需要重新访问某些设计。

38a50ada47fd5ea4

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="com.example.tiptime">

   <application ...>
       <activity android:name=".MainActivity"
           android:exported="true">
           <intent-filter>
               <action android:name="android.intent.action.MAIN" />

               <category android:name="android.intent.category.LAUNCHER" />
           </intent-filter>
       </activity>
   </application>

</manifest>

7. 正在添加动态配色

使用适当的 Material 3 主题后,我们可以通过添加一些小小的新增内容使界面变得动态。

借助 Dynamic Colors API,您可以将动态配色应用于所有 Activity

应用内、单个 activity 或单个 View 或 fragment 中。适用于

这个应用,我们将全局应用动态配色。

创建应用类文件

class TipTimeApplication: Application() {
    override fun onCreate() {
        // Apply dynamic color
        DynamicColors.applyToActivitiesIfAvailable(this)
    }
}

我们需要在 Android 清单中引用以下新创建的文件:

AndroidManifest.xml

< application android name=".TipTimeApplication
<!--- Other existing attributes –>

</application >

在 Android 12 及更高版本的系统中,系统会检查用户默认方案的壁纸)以生成多个色调调色板。这些调色板中的值用于创建 ThemeOverlay

DynamicColors 类会注册一个在 ActivityPreCreated 上截获的 ActivityLifecycleCallbacks,以应用系统创建的动态主题叠加层或您提供的动态主题叠加层。

eba71f96f4ba9cdf.png

8. 应用自定义主题叠加层

我们的工具可以导出主题叠加层,但是,如果您要覆盖少量属性,也可以手动创建它们。

主题叠加层旨在与另一个主题结合使用,并且仅提供在基本主题之上更改的值。

我们假设出于某种原因(比如品牌推广),我们需要主色调为红色阴影。我们可以使用以下文件和属性来完成此操作。

colors.xml

<resources>
    <color name="overlay_light_primary">#9C4146</color>
    <color name="overlay_light_onPrimary">#FFFFFF</color> 
    <color name= "overlay_light_primaryContainer">#FFDADB</color>
    <color name="overlay_light_onPrimaryContainer">#400008</color>
</resources >

themes_overlays.xml

<style name="AppTheme.Overlay" parent="ThemeOverlay.Material3.DynamicColors.Light">
    <item name="colorPrimary">@color/overlay_light_primary</item>
    <item name="colorOnPrimary">@color/overlay_light_onPrimary</item> 
    <item name="colorPrimaryContainer">@color/overlay_light_primaryContainer</item> 
    <item name="colorOnPrimaryContainer">@color/overlay_light_onPrimaryContainer<item>
</style>

对于上述代码,Android 12 会应用动态浅色主题,并将您的更改叠加到该主题之上。或者,您也可以使用任何有效的 ThemeOverlay 作为父项,包括以下任意一项:

ThemeOverlay.Material3.Light

ThemeOverlay.Material3.Dark

ThemeOverlay.Material3.DayNight ThemeOverlay.Material3.DynamicColors.Dark

ThemeOverlay.Material3.DynamicColors.DayNight

如需使用此主题叠加层而不是 Material 默认值,请将对 DynamicColors.applyToActivitiesIfAvailable 的调用更改为:

DynamicColors.applyToActivitiesIfAvailable(this, R.style.AppTheme_Overlay)

d87020776782036f.png

9. 向自定义属性添加动态配色

到目前为止,我们已经替换了 Material 3 主题中已存在的属性。还有一种可能是动态配色的情况,那就是我们可能需要分配一个或多个自定义属性。

应用选择启用动态配色后,可以使用 5 种色调调色板 - 3 种强调色和 2 种中性调色板,它们具有以下近似角色:

system_accent1

原色色调

system_accent2

次要色调

system_accent3

三级色调

system_neutral1

中性背景和表面

system_neutral2

中性表面和轮廓

每个调色板都有许多色调步骤,如白色

设置为黑色:0、10、50、100、200、300、400、500、600、700、800、900、1000。

在为动态配色设计界面时,您应该少考虑具体颜色,而应多考虑该组件的色调和亮度与设计系统中其他组件的关系。

假设您希望使用辅助强调色调色板为图标设置主题,并且您通过 attrs.xml 中的以下条目为图标着色添加了一个属性。

attrs.xml

<resources>
    <attr name="iconColor" format="color" />
</resources>

您的主题叠加层可能如下所示:

<style name="AppTheme.Overlay" parent="ThemeOverlay.Material3.DynamicColors.DayNight"> 
<item name="iconColor">@android:color/system_accent2_600</item>
</style>

当您重新安装应用并更换壁纸时,该应用会沿用以下辅助调色板。

11ef0035702640d9

264b2c2e74c5f574

这些调色板特定于 Android 12 (API 31),因此您需要将相关文件放在带有 -v31 后缀的文件夹中,除非应用的最低 SDK 设置为 31 或更高版本。

10. 总结

在此 Codelab 中,您已学到以下知识:

  • 添加依赖项以将主题升级到 Material 3。
  • 了解新的颜色组和角色。
  • 了解如何从静态主题迁移到动态配色。
  • 了解如何使用主题叠加层以及为自定义主题属性使用动态配色。