使用 Palette API 选择颜色

良好的视觉设计对于成功的应用至关重要,而配色方案是设计的主要组成部分。 Palette 库是一个 Jetpack 库,可从图像中提取主要颜色,以创建视觉效果出色的应用。

您可以使用 Palette 库来设计布局主题,并为应用中的视觉元素应用自定义颜色。例如,您可以使用调色板根据歌曲专辑封面为其创建颜色协调的标题卡,或者在应用的背景图片更改时调整应用工具栏的颜色。 Palette 对象可让您访问 Bitmap 图像中的颜色,同时还提供位图中的六种主要颜色配置文件,以指导您的设计选择

设置库

要使用 Palette 库,请将以下内容添加到您的 build.gradle

Kotlin

android {
    compileSdkVersion(33)
    ...
}

dependencies {
    ...
    implementation("androidx.palette:palette:1.0.0")
}

Groovy

android {
    compileSdkVersion 33
    ...
}

dependencies {
    ...
    implementation 'androidx.palette:palette:1.0.0'
}

创建调色板

通过 Palette 对象,您可以访问图像中的主色以及叠加文本的相应颜色。使用调色板设计应用样式,并根据给定的源图像动态更改应用的配色方案。

要创建调色板,首先从 Bitmap 实例化一个 Palette.Builder。然后,您可以使用 Palette.Builder 在生成调色板之前对其进行自定义。本部分介绍如何从位图图像生成和自定义调色板。

生成 Palette 实例

使用其 from(Bitmap bitmap) 方法生成一个 Palette 实例,以便首先从 Bitmap 创建 Palette.Builder

构建器可以同步或异步生成调色板。如果您想在调用方法的同一线程上创建调色板,请使用同步调色板生成。如果您在其他线程上异步生成调色板,请在调色板创建后立即使用 onGenerated() 方法访问调色板。

以下代码段提供了两种调色板生成类型的示例方法

Kotlin

// Generate palette synchronously and return it.
fun createPaletteSync(bitmap: Bitmap): Palette = Palette.from(bitmap).generate()

// Generate palette asynchronously and use it on a different thread using onGenerated().
fun createPaletteAsync(bitmap: Bitmap) {
    Palette.from(bitmap).generate { palette ->
        // Use generated instance.
    }
}

Java

// Generate palette synchronously and return it.
public Palette createPaletteSync(Bitmap bitmap) {
  Palette p = Palette.from(bitmap).generate();
  return p;
}

// Generate palette asynchronously and use it on a different thread using onGenerated().
public void createPaletteAsync(Bitmap bitmap) {
  Palette.from(bitmap).generate(new PaletteAsyncListener() {
    public void onGenerated(Palette p) {
      // Use generated instance.
    }
  });
}

如果您需要为已排序的图像或对象列表连续生成调色板,请考虑缓存 Palette 实例,以防止界面性能缓慢。切勿在主线程上创建调色板。

自定义调色板

使用 Palette.Builder,您可以通过选择结果调色板中的颜色数量、构建器用于生成调色板的图像区域以及调色板中包含的颜色来对其进行自定义。例如,您可以过滤掉黑色,或确保构建器仅使用图像上半部分来生成调色板。

使用 Palette.Builder 类中的以下方法微调调色板的大小和颜色

addFilter()
此方法会添加一个过滤条件,用于指示结果调色板中允许使用的颜色。传入您自己的 Palette.Filter 并修改其 isAllowed() 方法,以确定从调色板中过滤掉哪些颜色。
maximumColorCount()
此方法会设置调色板中的最大颜色数。默认值为 16,最佳值取决于源图像。对于风景图片,最佳值范围是 8-16,而包含人脸的图片通常为 24-32。颜色越多的调色板,Palette.Builder 生成所需的时间就越长。
setRegion()
此方法指示构建器在创建调色板时使用位图的哪个区域。您只能在从位图生成调色板时使用此方法,并且它不会影响原始图像。
addTarget()
通过此方法,您可以向构建器添加 Target 颜色配置文件,自行进行颜色匹配。如果默认 Target 不够用,高级开发者可以使用 Target.Builder 创建自己的 Target

提取颜色配置文件

根据 Material Design 标准,Palette 库会从图像中提取常用颜色配置文件。每个配置文件都由一个 Target 定义,根据饱和度、亮度以及人群数量(该颜色在位图中代表的像素数),从位图图像中提取的颜色会针对每个配置文件进行评分。对于每个配置文件,得分最高的颜色会定义给定图像的该颜色配置文件。

默认情况下,Palette 对象包含给定图像中的 16 种主要颜色。生成调色板时,您可以使用 Palette.Builder 自定义颜色数量。提取更多颜色可以为每个颜色配置文件提供更多潜在匹配项,但也会导致 Palette.Builder 在生成调色板时花费更长时间。

Palette 库会尝试提取以下六种颜色配置文件

  • 浅鲜艳
  • 鲜艳
  • 深鲜艳
  • 浅柔和
  • 柔和
  • 深柔和

Palette 中的每种 get<Profile>Color() 方法都会返回与特定配置文件关联的调色板颜色,其中 <Profile> 替换为六种颜色配置文件之一的名称。例如,获取深鲜艳颜色配置文件的示例方法是 getDarkVibrantColor()。并非所有图像都包含所有颜色配置文件,因此请提供要返回的默认颜色。

图 1 显示了一张照片及其通过 get<Profile>Color() 方法获得的对应颜色配置文件。

An image showing a sunset on the left and the extracted color palette on the right.
图 1. 一张示例图片及其在调色板默认最大颜色数 (16) 下提取的颜色配置文件。

使用色板创建配色方案

Palette 类还会为每个颜色配置文件生成 Palette.Swatch 对象。Palette.Swatch 对象包含该配置文件的关联颜色以及颜色的像素数量。

色板具有其他方法,可用于访问有关颜色配置文件的更多信息,例如 HSL 值和像素数量。您可以使用色板以及 getBodyTextColor()getTitleTextColor() 方法帮助创建更全面的配色方案和应用主题。这些方法返回适合在色板颜色上使用的颜色。

Palette 中的每种 get<Profile>Swatch() 方法都会返回与特定配置文件关联的色板,其中 <Profile> 替换为六种颜色配置文件之一的名称。虽然调色板的 get<Profile>Swatch() 方法不需要默认值参数,但如果图片中不存在特定配置文件,它们会返回 null。因此,在使用色板之前,请检查它是否为 null。例如,如果鲜艳色板不为 null,以下代码会从调色板获取标题文本颜色

Kotlin

val vibrant = myPalette.vibrantSwatch
// In Kotlin, check for null before accessing properties on the vibrant swatch.
val titleColor = vibrant?.titleTextColor

Java

Palette.Swatch vibrant = myPalette.getVibrantSwatch();
if(vibrant != null){
    int titleColor = vibrant.getTitleTextColor();
    // ...
}

要访问调色板中的所有颜色,getSwatches() 方法会返回从图像生成的所有色板的列表,包括标准六种颜色配置文件。

以下代码段使用上述代码段中的方法同步生成调色板,获取其鲜艳色板,并更改工具栏颜色以匹配位图图像。图 2 显示了结果图像和工具栏。

Kotlin

// Set the background and text colors of a toolbar given a bitmap image to
// match.
fun setToolbarColor(bitmap: Bitmap) {
    // Generate the palette and get the vibrant swatch.
    val vibrantSwatch = createPaletteSync(bitmap).vibrantSwatch

    // Set the toolbar background and text colors.
    // Fall back to default colors if the vibrant swatch isn't available.
    with(findViewById<Toolbar>(R.id.toolbar)) {
        setBackgroundColor(vibrantSwatch?.rgb ?:
                ContextCompat.getColor(context, R.color.default_title_background))
        setTitleTextColor(vibrantSwatch?.titleTextColor ?:
                ContextCompat.getColor(context, R.color.default_title_color))
    }
}

Java

// Set the background and text colors of a toolbar given a bitmap image to
// match.
public void setToolbarColor(Bitmap bitmap) {
    // Generate the palette and get the vibrant swatch.
    // See the createPaletteSync() method from the preceding code snippet.
    Palette p = createPaletteSync(bitmap);
    Palette.Swatch vibrantSwatch = p.getVibrantSwatch();

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

    // Load default colors.
    int backgroundColor = ContextCompat.getColor(getContext(),
        R.color.default_title_background);
    int textColor = ContextCompat.getColor(getContext(),
        R.color.default_title_color);

    // Check that the Vibrant swatch is available.
    if(vibrantSwatch != null){
        backgroundColor = vibrantSwatch.getRgb();
        textColor = vibrantSwatch.getTitleTextColor();
    }

    // Set the toolbar background and text colors.
    toolbar.setBackgroundColor(backgroundColor);
        toolbar.setTitleTextColor(textColor);
}
An image showing a sunset and a toolbar with TitleTextColor inside
图 2. 一张示例图片及其鲜艳颜色工具栏和对应的标题文本颜色。