使用 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 实例以防止 UI 性能下降。不要在您的主线程上创建调色板。

自定义您的调色板

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。例如,以下代码在 Vibrant 色样不为 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. 一个示例图像,其工具栏颜色为鲜艳色,以及相应的标题文本颜色。