The Android Developer Challenge is back! Submit your idea before December 2.

Selecciona colores con la API de Palette

Un buen diseño visual es esencial para el éxito de una app, y los esquemas de color son un componente principal del diseño. La biblioteca de paletas es una biblioteca de compatibilidad que extrae colores prominentes de las imágenes para ayudarte a crear apps visualmente atractivas.

Puedes usar la biblioteca de paletas para diseñar temas y aplicar colores personalizados a elementos visuales en tu app. Por ejemplo, puedes usar una paleta para crear una tarjeta de título de una canción con coordinación de colores basada en la portada del álbum o para modificar el color de la barra de herramientas de una app cuando cambia la imagen de fondo. El objeto Palette te da acceso a los colores en una imagen Bitmap y proporciona seis perfiles de color principales del mapa de bits para ayudarte a elegir opciones de diseño.

Configura la biblioteca

Para usar la biblioteca de paletas, instala la biblioteca de compatibilidad de Android o actualízala a la versión 24.0.0 o una posterior, y sigue las instrucciones de Cómo agregar bibliotecas de compatibilidad para agregar la biblioteca de paletas a tu proyecto de desarrollo de apps.

Asegúrate de que la versión especificada en el identificador de dependencia coincida con el compileSdkVersion de la app, configurado en el archivo build.gradle:

    android {
      compileSdkVersion 28
      ...
    }

    dependencies {
      ...
      implementation 'com.android.support:palette-v7:28.0.0'
    }
    

Nota: Si usas el complemento de Android para Gradle 3.0.0 o versiones posteriores, usa la palabra clave "implementation". Si usas otra versión del complemento de Android para Gradle, usa la palabra clave "compile".

Para obtener más información sobre cómo agregar la dependencia de la paleta, consulta artículos sobre la función de la paleta en la documentación de la biblioteca.

Crea una paleta

Un objeto Palette te da acceso a los colores primarios de una imagen, así como a los colores correspondientes para el texto superpuesto. Usa paletas para diseñar el estilo de tu app y cambiar dinámicamente el esquema de colores de tu app en función de una imagen de origen determinada.

Para crear una paleta, primero crea una instancia de un Palette.Builder desde un Bitmap. Luego, puedes usar Palette.Builder para personalizar la paleta antes de generarla. En esta sección, se describe la personalización y generación de paletas a partir de una imagen de mapa de bits.

Genera una instancia de paleta

Genera una instancia Palette con el método from(Bitmap bitmap) de para crear primero Palette.Builder desde Bitmap. El creador puede generar la paleta de forma síncrona o asíncrona.

Usa la generación síncrona de paleta si deseas crear la paleta en el mismo subproceso que el método que se está llamando. Si generas la paleta de forma asíncrona en un subproceso diferente, usa el método onGenerated() para acceder a la paleta inmediatamente después de crearla.

En el siguiente fragmento de código, se proporcionan métodos de ejemplo para ambos tipos de generación de paletas:

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

Si necesitas generar paletas de forma continua para una lista ordenada de objetos o imágenes, considera almacenar en caché las instancias Palette para evitar un rendimiento lento de la IU. Tampoco debes crear las paletas en el subproceso principal.

Personaliza tu paleta

El Palette.Builder te permite personalizar la paleta. Para ello, puedes elegir la cantidad de colores, el área de la imagen que utiliza el creador para generarla y qué colores se permiten en ella. Por ejemplo, puedes filtrar el color negro o asegurarte de que el creador use solamente la mitad superior de una imagen para generar la paleta.

Ajusta el tamaño y los colores de la paleta con los siguientes métodos de la clase Palette.Builder:

addFilter()
Este método agrega un filtro que indica qué colores están permitidos en la paleta resultante. Pasa en tu propio Palette.Filter y modifica su método isAllowed() para determinar qué colores se filtran de la paleta.
maximumColorCount()
Este método establece la cantidad máxima de colores en la paleta. El valor predeterminado es 16, y el valor óptimo depende de la imagen de origen. Para los paisajes, los valores óptimos varían entre 8 y 16, mientras que las imágenes con rostros suelen tener valores comprendidos entre 24 y 32. El Palette.Builder tarda más en generar paletas con más colores.
setRegion()
Este método indica qué área del mapa de bits utiliza el creador cuando genera la paleta. Solo puedes usar este método cuando generas la paleta a partir de un mapa de bits, y no afecta la imagen original.
addTarget()
Este método permite realizar una coincidencia de colores propia agregando un perfil de color Target al creador. Si los Target predeterminados no alcanzan, los desarrolladores avanzados pueden crear Target propios usando un Target.Builder.

Extrae perfiles de color

Según los estándares de Material Design, la biblioteca de paletas extrae los perfiles de color utilizados comúnmente de una imagen. Cada perfil se define con un Target, y los colores extraídos de la imagen de mapa de bits se califican comparando cada perfil en función de la saturación, la luminancia y la resolución (cantidad de píxeles en el mapa de bits representada por el color). Para cada perfil, el color con la mejor calificación define ese perfil de color para la imagen.

De manera predeterminada, un objeto Palette contiene 16 colores primarios de una imagen determinada. Cuando generas la paleta, puedes personalizar la cantidad de colores con Palette.Builder. Extraer más colores proporciona más coincidencias posibles para cada perfil de color, pero también hace que Palette.Builder tarde más en generar la paleta.

En la biblioteca de paletas, se intenta extraer los siguientes seis perfiles de color:

  • Vibrante claro
  • Vibrante
  • Vibrante oscuro
  • Tenue claro
  • Tenue
  • Tenue oscuro

Cada uno de los métodos get<Profile>Color() de Palette muestra el color en la paleta asociada con ese perfil específico, donde <Profile> se reemplaza por el nombre de uno de los seis perfiles de color. Por ejemplo, el método para obtener el perfil de color vibrante oscuro es getDarkVibrantColor(). Como no todas las imágenes contendrán todos los perfiles de color, también debes proporcionar un color predeterminado para mostrar.

En la figura 1, se muestran una foto y sus perfiles de color correspondientes de los métodos get<Profile>Color().

Figura 1: Una imagen de ejemplo y los perfiles de color extraídos dada la cantidad máxima de colores predeterminada (16) para la paleta.

Usa muestras para crear esquemas de colores

La clase Palette también genera objetos Palette.Swatch para cada perfil de color. Los objetos Palette.Swatch contienen el color asociado a ese perfil, así como la resolución del color en píxeles.

Las muestras tienen métodos adicionales para acceder a más información sobre el perfil de color, como los valores HSL y la resolución en píxeles. Puedes usar muestras para crear esquemas de colores más completos y temas de apps con los métodos getBodyTextColor() y getTitleTextColor(). Estos métodos muestran colores apropiados para usar sobre el color de la muestra.

Cada uno de los métodos get<Profile>Swatch() de Palette presenta la muestra asociada con ese perfil en particular, en la que <Profile> se reemplaza por el nombre de uno de los seis perfiles de color. Aunque los métodos get<Profile>Swatch() de la paleta no requieren parámetros de valores predeterminados, muestran null si ese perfil específico no existe en la imagen. Por lo tanto, debes verificar que una muestra no sea nula antes de usarla. Por ejemplo, el siguiente código obtiene el color del texto del título de una paleta si la muestra vibrante no es 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 acceder a todos los colores de una paleta, el método getSwatches() presenta una lista de todas las muestras generadas a partir de una imagen, incluidos los seis perfiles de colores estándar.

En el siguiente fragmento de código, se usan los métodos de los fragmentos de código anteriores para generar una paleta de forma síncrona, obtener su muestra de vibrante y cambiar los colores de una barra de herramientas para que coincida con la imagen del mapa de bits. En la figura 2, se muestran la imagen y la barra de herramientas 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 is not 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 code snippet above
        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);
    }
    

Figura 2: Una imagen de ejemplo con la barra de herramientas de colores vibrantes y el color del texto del título correspondiente.