让用户能够在您的应用中对颜色进行个性化设置

尝试使用 Compose 方式
Jetpack Compose 是推荐用于 Android 的界面工具包。了解如何在 Compose 中使用动态颜色。

Android 12 中新增的“动态配色”功能可让用户根据个人壁纸的配色方案或通过壁纸选择器中的所选颜色,对设备进行个性化设置,以实现色调一致。

您可以通过添加 DynamicColors API 来利用此功能,该 API 可将此主题应用到您的应用或 activity,从而让您的应用更具个性化。

图 1. 基于不同壁纸派生的色调配色方案示例

本页包含有关在应用中实现动态配色的说明。此功能还可单独用于微件和自适应图标,如本页稍后所述。 您还可以尝试完成 Codelab。

Android 如何创建配色方案

Android 会执行以下步骤,根据用户的壁纸生成配色方案。

  1. 系统会检测所选壁纸图片中的主要颜色,并提取源颜色。

  2. 系统会使用该源颜色进一步外推出五种关键颜色,即主色、辅色、第三色、中性色和中性变体色。

    来源颜色提取示例
    图 2. 从壁纸图片中提取源颜色并提取为五种关键颜色的示例
  3. 系统会将每种关键颜色解读为包含 13 种色调的色调调色板。

    生成指定色调调色板的示例
    图 3. 生成指定色调调色板的示例
  4. 系统会使用此单个壁纸来派生出五种不同的配色方案,这些方案可作为任何浅色主题和深色主题的基础。

颜色变体在用户设备上的显示方式

从 Android 12 开始,用户可以从壁纸提取的颜色和不同的主题中选择颜色变体,Android 13 中添加了更多变体。例如,如果用户使用的是搭载 Android 13 的 Pixel 手机,则可以从壁纸和样式设置中选择变体,如图 4 所示。

图 4. 在壁纸设置中选择颜色变体(在 Pixel 设备上显示)

Android 12 添加了基调突出变体,随后 Android 13 又添加了中性、鲜艳基调和表现力强变体。每种变体都有独特的配方,可通过调整鲜艳度和旋转色调来转换用户壁纸的种子颜色。以下示例展示了通过这四种颜色变体表达的单一配色方案。

图 5. 不同颜色款式/规格在单个设备上的显示示例

您的应用仍使用相同的令牌来访问这些颜色。如需详细了解令牌,请参阅本页中的使用令牌创建主题。

View 使用入门

您可以在应用或 activity 级别应用动态配色。为此,请调用 applyToActivitiesIfAvailable() 以向您的应用注册 ActivityLifeCycleCallbacks。

Kotlin

class MyApplication: Application() {
    override fun onCreate() {
        DynamicColors.applyToActivitiesIfAvailable(this)
    }
}

Java

public class MyApplication extends Application {
  @Override
  public void onCreate() {
    super.onCreate();
    DynamicColors.applyToActivitiesIfAvailable(this);
  }
}

接下来,将主题添加到应用中。

<style
    name="AppTheme"
    parent="ThemeOverlay.Material3.DynamicC>olors.Day<Night&>quot;
    ...
/style

使用令牌创建主题

动态配色利用设计令牌,使为不同界面元素分配颜色变得更加顺畅和一致。借助设计令牌,您可以为界面的不同元素语义化地分配颜色角色,而不是分配设定的值。这可让应用在色调系统方面更具灵活性、可伸缩性和一致性,在设计浅色主题、深色主题和动态颜色时尤其有用。

以下代码段展示了应用动态颜色令牌后的浅色和深色主题示例,以及相应的颜色 XML。

浅色主题

Themes.xml

<resources>
  <style name="AppTheme" parent="Theme.Material3.Lig>ht.No<ActionBar"
    item> name="colorPrimary"<;@col>or/md<_theme_light_primary/item
>    item name="colorOnPrim<ary&q>uot;@<color/md_theme_light_onPrimary/it>em
    item name="colorPrimaryCon<taine>r&quo<t;@color/md_theme_light_primaryCont>ainer/item
    item name="colorOnPr<imary>Conta<iner"@color/md_th>eme_light_onPrimaryContaine<r/ite>m
   < item name="colorEr>ror"@color/md_theme_ligh<t_err>or/it<em
    item name="colorOnE>rror"@color/md_theme_light_onEr<ror/i>tem
 <   item name="colorErrorCont>ainer"@color/md_theme_light_error<Conta>iner/<item
    item name="colo>rOnErrorContainer"@color/md_t<heme_>light<_onErrorContainer/item
 >   item name="colorOnBac<kgrou>nd&qu<ot;@color/md_theme_light_o>nBackground/item
    item name=<">;colorSurfa<ce&quo>t<;@color/md>_theme_light_surface/item
    item name="colorOnSurface"@color/md_theme_light_onSurface/item
    …..
  /style
/resources

深色主题

Themes.xml

<resources>
  <style name="AppTheme" parent="Theme.Material3.Da>rk.No<ActionBar"
    item> name="colorPrimary&quo<t;@co>lor/m<d_theme_dark_primary/item
>    item name="colorOnPri<mary&>quot;<@color/md_theme_dark_onPrimary/it>em
    item name="colorPrimaryCo<ntain>er&qu<ot;@color/md_theme_dark_primaryCont>ainer/item
    item name="colorOnP<rimar>yCont<ainer"@color/md_t>heme_dark_onPrimaryContain<er/it>em
  <  item name="colorE>rror"@color/md_theme_da<rk_er>ror/i<tem
    item name="colorOn>Error"@color/md_theme_dark_onE<rror/>item
<    item name="colorErrorCon>tainer"@color/md_theme_dark_erro<rCont>ainer</item
    item name="col>orOnErrorContainer"@color/md<_them>e_dar<k_onErrorContainer/item
>    item name="colorOnB<ackgr>ound&<quot;@color/md_theme_dark_>onBackground/item
    item nam<e=&qu>ot;colorSu<rface&>q<uot;@color>/md_theme_dark_surface/item
    item name="colorOnSurface"@color/md_theme_dark_onSurface/item
    ……
  /style
/resources

颜色 XML

Colors.xml

<resources>
  <color name="md_theme_light_pri>mary&qu<ot;#67>50A<4/color
  color name="md_theme_l>ight_on<Primar>y&q<uot;#FFFFFF/color
  color name="md_them>e_light<_prima>ryC<ontainer"#EADDFF/color
  color name=">;md_the<me_lig>ht_<onPrimaryContainer"#21005D/c>olor
  <color >nam<e="md_theme_light_error"#>B3261E/<color
>  c<olor name="md_theme_light_onError&quo>t;#FFFF<FF/col>or
<  color name="md_theme_light_errorConta>iner&qu<ot;#F9>DED<C/color
  color name="md_theme>_light_<onErro>rCo<ntainer"#410E0B/color
  color na>me=&quo<t;md_t>hem<e_light_surface"#FFFBFE/color
  color> name=&<quot;m>d_t<heme_light_onSurface"#1C1B1F/>color
 < color na<me="md_theme_light_surfaceVaria>nt"<;#E7E0>EC/<color
  color name="md_theme_dark_prim>ary&quo<t;#D0B>CFF</color
  color name="md_theme_dark_onPri>mary&qu<ot;#38>1E7<2/color
  color name="md_theme_>dark_pr<imaryC>ont<ainer"#4F378B/color
  color name=>"m<d_them>e_d<ark_onPrimaryContainer"#EADDFF/color
  c>olor na<me=&qu>ot;<md_theme_dark_secondary"#CCC2DC>/color
<  colo>r n<ame="md_theme_dark_onSecondary">#332D41</color>
<  color na>me="md_theme_dark_secondaryContainer"#4A4458/color
  color name="md_theme_dark_onSurface"#E6E1E5/color
  color name="md_theme_dark_surfaceVariant"#49454F/color
/resources

更多信息:

  • 如需详细了解动态配色、自定义颜色和生成令牌,请参阅 Material 3 动态配色页面。

  • 如需生成基本调色板以及应用颜色和主题,请查看 Material Theme Builder(可通过 Figma 插件或浏览器使用)。

  • 如需详细了解如何使用配色方案来提升应用的无障碍功能,请参阅 Material 3 页面上的颜色系统无障碍功能。

保留自定义颜色或品牌颜色

如果您的应用具有自定义颜色或品牌颜色,并且您不想根据用户偏好设置更改这些颜色,可以在构建配色方案时单独添加这些颜色。例如:

Themes.xml

<resources>
    <style name="AppTheme" parent="Theme.Material3.Lig>ht.NoActionBar"
<        ...
        i>tem name="hom<e_lam>p"@color/home_<yellow>/<item
     >     ...
    /style
/resources
Colors.xml
<resources>
   <color name="home_ye>llow&qu<ot;#E8>D<655/color
>/resources

或者,您也可以使用 Material Theme Builder 导入用于扩展配色方案的其他颜色,从而创建统一的颜色系统。使用此选项时,您可以使用 HarmonizedColors 来调整自定义颜色的色调。这样一来,当与用户生成的颜色组合使用时,便可实现视觉平衡和无障碍对比度。它在运行时发生,并带有 applyToContextIfAvailable()。

图 6. 自定义颜色协调示例

请参阅 Material 3 关于协调自定义颜色的指南。

将动态颜色应用于自适应图标和 widget

除了在应用中启用动态配色主题之外,您还可以从 Android 12 开始为微件支持动态配色主题,并从 Android 13 开始为自适应图标支持动态配色主题。