Selecionar cores com a API Palette

Um bom design visual é essencial para um app de sucesso, e os esquemas de cores são um componente principal do design. A biblioteca Palette é uma biblioteca do Jetpack que extrai cores em destaque das imagens para criar apps visualmente atraentes.

Você pode usar a biblioteca Palette para criar temas de layout e aplicar cores personalizadas a elementos visuais no seu app. Por exemplo, você pode usar uma paleta para criar um cartão de título coordenado para uma música com base na capa do álbum ou ajustar a cor da barra de ferramentas de um app quando a imagem de plano de fundo mudar. O objeto Palette dá acesso às cores em uma imagem Bitmap, além de fornecer seis perfis de cores principais do bitmap para informar suas escolhas de design.

Configurar a biblioteca

Para usar a biblioteca Palette, adicione o seguinte ao seu 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'
}

Criar uma paleta

Um objeto Palette oferece acesso às cores primárias de uma imagem, bem como às cores correspondentes do texto sobreposto. Use paletas para projetar o estilo do app e mudar dinamicamente o esquema de cores com base em uma determinada imagem de origem.

Para criar uma paleta, primeiro instancie um Palette.Builder de um Bitmap. Você pode usar Palette.Builder para personalizar a paleta antes de gerá-la. Esta seção descreve a geração e personalização da paleta de uma imagem em bitmap.

Gerar uma instância de Palette

Gere uma instância de Palette usando o método from(Bitmap bitmap) para criar um Palette.Builder com base em um Bitmap.

O criador pode gerar a paleta de forma síncrona ou assíncrona. Use a geração síncrona de paleta se quiser criar a paleta na mesma linha de execução do método que está sendo chamado. Se você gerar a paleta de forma assíncrona, em uma linha de execução diferente, use o método onGenerated() para acessar a paleta imediatamente após ela ser criada.

O snippet de código abaixo mostra métodos de exemplo para os dois tipos de geração de paleta:

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.
    }
  });
}

Se você precisa gerar paletas continuamente para uma lista classificada de imagens ou objetos, faça o armazenamento em cache das instâncias Palette para evitar um desempenho lento da interface. Não crie as palettes na linha de execução principal.

Personalizar sua paleta

O Palette.Builder permite personalizar sua paleta escolhendo quantas cores estão na paleta resultante, qual área da imagem o criador usa para gerar a paleta e quais cores serão incluídas na paleta. Por exemplo, você pode filtrar a cor preta ou garantir que o builder use apenas a metade de cima de uma imagem para gerar sua paleta.

Ajuste o tamanho e as cores da paleta com estes métodos da classe Palette.Builder:

addFilter()
Este método adiciona um filtro que indica quais cores são permitidas na paleta resultante. Transmita seu próprio Palette.Filter e modifique o método isAllowed() para determinar quais cores serão filtradas da paleta.
maximumColorCount()
Este método configura o número máximo de cores na paleta. O valor padrão é 16, e o valor ideal depende da imagem de origem. Para paisagens, os valores ideais variam de 8 a 16, enquanto imagens com rostos geralmente têm valores de 24 a 32. O Palette.Builder leva mais tempo para gerar paletas com mais cores.
setRegion()
Esse método indica qual área do bitmap o builder usa ao criar a paleta. Você só pode usar esse método ao gerar a paleta com um bitmap, e ele não afeta a imagem original.
addTarget()
Esse método permite que você faça sua própria correspondência de cores adicionando um perfil de cores Target ao builder. Se o Target padrão não for suficiente, os desenvolvedores avançados poderão criar o próprio Target usando um Target.Builder.

Extrair perfis de cores

Com base nos padrões do Material Design, a biblioteca Palette extrai os perfis de cores mais usados de uma imagem. Cada perfil é definido por um Target, e as cores extraídas da imagem de bitmap são pontuadas em cada perfil com base na saturação, luminância e preenchimento (número de pixels no bitmap representados pela cor). Para cada perfil, a cor com a melhor pontuação define esse perfil de cor para a imagem especificada.

Por padrão, um objeto Palette contém 16 cores primárias de uma determinada imagem. Ao gerar sua paleta, você pode personalizar o número de cores dela usando o Palette.Builder. A extração de mais cores oferece mais possíveis correspondências para cada perfil de cor, mas também faz com que Palette.Builder demore mais ao gerar a paleta.

A biblioteca Palette tenta extrair os seis perfis de cores a seguir:

  • Light Vibrant
  • Vibrant
  • Dark Vibrant
  • Light Muted
  • silenciados;
  • Dark Muted

Cada um dos métodos get<Profile>Color() em Palette retorna a cor na paleta associada a esse perfil específico, em que <Profile> é substituído pelo nome de um dos seis perfis de cores. Por exemplo, o método para conseguir o perfil de cor Darkur é getDarkVibrantColor(). Como nem todas as imagens contêm todos os perfis de cores, forneça uma cor padrão para retornar.

A Figura 1 mostra uma foto e os perfis de cores correspondentes dos métodos get<Profile>Color().

Uma imagem mostrando o pôr do sol à esquerda e a paleta de cores extraída à direita.
Figura 1. Exemplo de imagem e os perfis de cores extraídos, considerando a contagem máxima de cores padrão (16) para a paleta.

Usar amostras para criar esquemas de cores

A classe Palette também gera objetos Palette.Swatch para cada perfil de cor. Os objetos Palette.Swatch contêm a cor associada a esse perfil, bem como o preenchimento da cor em pixels.

As amostras têm outros métodos para acessar mais informações sobre o perfil de cor, como valores de HSL e preenchimento de pixels. Você pode usar amostras para ajudar a criar esquemas de cores e temas de apps mais abrangentes com os métodos getBodyTextColor() e getTitleTextColor(). Esses métodos retornam cores adequadas para uso sobre a cor da amostra.

Cada método get<Profile>Swatch() de Palette retorna a amostra associada a esse perfil específico, em que <Profile> é substituído pelo nome de um dos seis perfis de cores. Embora os métodos get<Profile>Swatch() da paleta não exijam parâmetros de valor padrão, eles retornarão null se esse perfil específico não existir na imagem. Portanto, verifique se uma amostra não é nula antes de usá-la. Por exemplo, o código a seguir acessa a cor do texto do título de uma paleta se a amostra "Vibrante" não for nula:

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();
    // ...
}

Para acessar todas as cores em uma paleta, o método getSwatches() retorna uma lista de todas as amostras geradas a partir de uma imagem, incluindo os seis perfis de cores padrão.

O snippet de código a seguir usa os métodos dos snippets de código anteriores para gerar uma paleta de forma síncrona, receber a amostra vibrante e mudar as cores de uma barra de ferramentas para corresponder à imagem de bitmap. A Figura 2 mostra a imagem e a barra de ferramentas resultantes.

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);
}
Uma imagem mostrando um pôr do sol e uma barra de ferramentas com a TitleTextColor dentro
Figura 2. Exemplo de imagem com barra de ferramentas de cor vibrante e a cor do texto do título correspondente.