Material Design – Palette

Si vous avez suivi la Google IO 2014, vous aurez forcément pu remarquer que la couleurs de leur interface s’adaptaient en fonction des images affichées.

Cette technologie a été apportée dans le Material Design, sous le nom de Palette, voyons ensemble comment l’utiliser !

color

Cette librairie est fournit dans les librairies de support v7, il faut donc commencer par l’importer dans notre projet

guild.gradle

dependencies {
    compile 'com.android.support:appcompat-v7:22.1.1'
    compile 'com.android.support:palette-v7:22.1.1'

    //j'utiliserai ici picasso pour le chargement d'images
    compile 'com.squareup.picasso:picasso:2.5.2'
}

Afin de générer la palette, il suffit d’utiliser un Palette.Builder en lui fournissant une Bitmap

PaletteAsyncListener paletteListener = new Palette.PaletteAsyncListener() {
       @Override
       public void onGenerated(Palette palette) {
             //c'est ici que les couleurs sont générées
       }
}
new Palette.Builder(bitmap).generate(paletteListener);

J’utilise ici un Palette.PaletteAsynckListener afin de générer ma palette en tâche de fond et donc ne pas bloquer l’interface graphique

La Palette va essayer de trouver les 16 couleurs à partir de l’image, qu’elle va répartir au sein de ses 6 profils :

  • Vibrant
  • Vibrant Dark
  • Vibrant Light
  • Muted
  • Muted Dark
  • Muted Light

 

Afin de récupérer ces profils, nommés ici Swatch il suffit de les demander à la palette récemment générée:

Palette.Swatch vibrantSwatch = palette.getVibrantSwatch();
Palette.Swatch vibrantLightSwatch = palette.getLightVibrantSwatch();
Palette.Swatch vibrantDarkSwatch = palette.getDarkVibrantSwatch();
Palette.Swatch mutedSwatch = palette.getMutedSwatch();
Palette.Swatch mutedLightSwatch = palette.getLightMutedSwatch();
Palette.Swatch mutedDarkSwatch = palette.getDarkMutedSwatch();

paletteSample 2

Attention cependant, la Palette n’arrive pas toujours à générer tous les profils à partir d’une image, veilliez bien à tester si la swatch n’est pas null !

Swatch

Chaque swatch est composé de 3 couleurs

  • Rgb : utilisable en tant que couleur d’arrière plan
  • BodyTextColor : utilisable en tant que couleur de texte
  • TitleTextColor : utilisable en tant que couleur de texte pour le titre d’une vue

Voici comment récupérer ces couleurs

Palette.Swatch vibrant = palette.getVibrantSwatch(); //prenons le VibrantS comme exemple
int colorRgb = vibrant.getRgb();
int colorText = vibrant.getBodyTextColor();
int colorTitle = vibrant.getTitleTextColor();

Dans l’image ci dessous, les couleurs suivantes ont été générés par la Palette

  • Rgb : #fff69c39rgb
  • BodyTextColor : #77000000text
  • TitleTextColor : #9f000000title

 

paletteSample 3

 

Exemple

Essayons d’utiliser la palette afin de récupérer les différents profils de l’image suivante

maxresdefault

Mise en place

Pour commencer : le code de mon activité, je récupère ici simplement les vues définies dans mon @layout/layout activity_main.xml

J’ai placé le code de ce layout à la fin du tutoriel.

public class MainActivity extends AppCompatActivity {

    ImageView imageView;

    TextView textVibrant;
    TextView textVibrantLight;
    TextView textVibrantDark;
    TextView textMuted;
    TextView textMutedLight;
    TextView textMutedDark;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        imageView = (ImageView) findViewById(R.id.image);

        textVibrant = (TextView) findViewById(R.id.textVibrant);
        textVibrantLight = (TextView) findViewById(R.id.textVibrantLight);
        textVibrantDark = (TextView) findViewById(R.id.textVibrantDark);
        textMuted = (TextView) findViewById(R.id.textMuted);
        textMutedLight = (TextView) findViewById(R.id.textMutedLight);
        textMutedDark = (TextView) findViewById(R.id.textMutedDark);
    }
}

Layout

layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    >

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        android:adjustViewBounds="true"
        tools:background="#AAA"
        android:layout_centerHorizontal="true"
         />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/image"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="30dp"
        android:gravity="center"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textVibrant"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Vibrant" />

            <TextView
                android:id="@+id/textVibrantDark"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Vibrant dark" />

            <TextView
                android:id="@+id/textVibrantLight"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Vibrant Light" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:id="@+id/textMuted"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Muted" />

            <TextView
                android:id="@+id/textMutedDark"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Muted dark" />

            <TextView
                android:id="@+id/textMutedLight"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center"
                android:padding="20dp"
                android:text="Muted Light" />
        </LinearLayout>
    </LinearLayout>

</RelativeLayout>

Ce qui donne dans la preview :

layout-2015-05-26-170540

Chargement de l’image

Je vais ajouter à la suite de la fonction onCreate le code permettant de télécharger l’image via Picasso.
Le 2 ème argument passé au into() est le listener. Je l’utilise ici afin d’être notifié au moment où l’image a finit d’être chargée.

String url = "http://i.ytimg.com/vi/aNHOfJCphwk/maxresdefault.jpg";

//j'utilise Picasso afin de récupérer l'image
Picasso.with(this).load(url).fit().centerCrop().into(
        imageView,

        //j'écoute le chargement via picasso
        new Callback() {
            @Override

            //puis lorsque l'image a bien été chargée
            public void onSuccess() {
                //retrouver le bitmap téléchargé par Picasso
                Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();

                //demande à la palette de générer ses coleurs, de façon asynchrone
                //afin de ne pas bloquer l'interface graphique
                new Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(Palette palette) {
                        //lorsque la palette est générée, je l'utilise sur mes textViews
                        appliquerPalette(palette);
                    }
                });
            }

            @Override
            public void onError() {

            }
        });

Initialisation de la Palette

J’utilise la méthode suivante afin de récupérer l’image chargée par Picasso

Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();

Puis l’envoie à la Palette, qui va générer ses différents profils en tâche de fond

new Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() {
                    @Override
                    public void onGenerated(Palette palette) {
                        appliquerPalette(palette);
                    }
                });

Utiliser la palette

Une fois la palette générée, je vais vous montrer comment utiliser simplement le swatch

//je récupère le Swatch Vibrant
Palette.Swatch vibrant = palette.getVibrantSwatch();
if (vibrant != null) { //il se peut que la palette ne génère pas tous les swatch

    //j'utilise getRgb() en tant que couleurs de fond te ma textView
    textVibrant.setBackgroundColor(vibrant.getRgb());

    //getBodyTextColor() est prévu pour être affiché dessus une vue en background getRgb()
    textVibrant.setTextColor(vibrant.getBodyTextColor());
}

Je n’écrit ici que la gestion du Swatch Vibrant, l’utilisation des autres profils s’effectue de la même façon

Résultat :

paletteSample

 

Vous pouvez retrouver les sources de ce tutoriel sur github 🙂

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *