preface

Palette is a new feature in the Android L SDK that allows you to extract a prominent color (the main color) from an image using the Palette. Once you get the color, you can assign the color value to the ActionBar, status bar, etc. So as to achieve the unity of the interface tone, make the interface beautiful and harmonious.

The Palette principle: By obtaining a bitmap, the method is analyzed to take out LightVibrantSwatch, DarkVibrantSwatch, LightMutedSwatch, DarkMutedSwatch samples, and then get RGB values.


Palette

methods introduce
Palette.Builder Generator class that generates an instance of the Palette
Palette.Filter Filter interface, so that the Palette has more delicate color filtering
Palette.PaletteAsyncListener Asynchronous load listening
pattle.Swatch Provide color samples to obtain results
from(List<Palette.Switch> switches) The Palette is generated from the preset Palette.Swatch color sample list
from(Bitmap bitmap) Build the Palette by returning the Palette.Builder instance
palette.getDarkMutedColor(Color.BLUE) Get a soft dark color (passable default)
palette.getDarkVibrantColor(Color.BLUE) Get active dark color (passable default)
palette.getLightMutedColor(Color.BLUE) Get soft and bright colors (passable default)
palette.getLightVibrantColor(Color.BLUE) Get active bright colors (passable defaults)
palette.getVibrantColor(Color.BLUE) Gets the most active color in the image (or the most active color in the entire image) (passable default value)
palette.getMutedColor(Color.BLUE) Get one of the softest colors in the image (transferable default)
  • Palette.Builder Builder class, which generates an instance of the Palette

  • The Palette.Filter interface allows the Palette to have a more delicate color Filter

  • The Palette. PaletteAsyncListener asynchronous load monitoring

  • Pattle. Swatch provides color samples to get results

  • From (List switches) generate the Palette from the preset Palette.Swatch color sample List

  • From (Bitmap Bitmap) builds the Palette by returning the instance Palette.Builder

  • Palette. GetDarkMutedColor (Color. BLUE) access to a soft dark Color (the default)

  • Palette. GetDarkVibrantColor (Color. BLUE) access to the active dark Color (the default)

  • Palette. GetLightMutedColor (Color. BLUE) access to a soft bright Color (the default)

  • Palette. GetLightVibrantColor (Color. BLUE) access to active bright Color (the default)

  • Palette. GetVibrantColor (color.blue) retrieves the most active Color in the image (or the most active Color in the entire image) (passable default)

  • Palette. GetMutedColor (color.blue) Gets the softest Color in the image (passable default)

Two, basic use

1. Import dependencies

implementation 'androidx. The palette: palette: 1.0.0'
Copy the code

Create it on the Palette

There are two ways to create the Palette: synchronous and asynchronous. In the development, we will use asynchronous mode for time-consuming operations to improve application performance.

Bitmap bm =BitmapFactory.decodeResource(getResources(),R.drawable.kale);
/ / synchronize
Palette.Builder builder = Palette.from(bm);
Palette palette=builder.generate();
/ / asynchronous
builder.generate(bitmap, new Palette.PaletteAsyncListener() {  @Override  public void onGenerated(Palette palette) {  } } Copy the code

3. Get the color attribute from the Palette

The following highlighted colors can be analyzed and extracted from the Palette, which can be used flexibly in the application environment, as shown in the figure below. The BitMap object of the picture in the screen can be obtained, and related properties can be extracted from the Palette to set the background color in the TextView.

Bitmap bitmap = ((BitmapDrawable) imageView.getDrawable()).getBitmap();
Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {
    @Override
    public void onGenerated(@Nullable Palette palette) {
        // Get a soft dark color (passable default)
 int darkMutedColor = palette.getDarkMutedColor(Color.BLUE);// If not, return the default color  // Get soft bright colors (passable default)  int lightMutedColor = palette.getLightMutedColor(Color.BLUE);  // Get active dark color (passable default)  int darkVibrantColor = palette.getDarkVibrantColor(Color.BLUE);  // Get active bright color (passable default)  int lightVibrantColor = palette.getLightVibrantColor(Color.BLUE);  // Get the softest color in the image (passable default)  int mutedColor = palette.getMutedColor(Color.BLUE);  // Get the most active color in the image (or the most active color in the whole image)  int vibrantColor = palette.getVibrantColor(Color.BLUE);  // Get a sample of a specific color  Palette.Swatch lightVibrantSwatch = palette.getVibrantSwatch();  // Google recommended: the overall color of the picture RGB blend value -- the main hue  int rgb = lightVibrantSwatch.getRgb();  // Google recommended: the color of the text in the middle of the image  int bodyTextColor = lightVibrantSwatch.getBodyTextColor();  // Google recommended: as the title color (has a certain color value and image contrast)  int titleTextColor = lightVibrantSwatch.getTitleTextColor();  // Color vector  float[] hsl = lightVibrantSwatch.getHsl();  // Analyze how many pixels the color occupies in the image  int population = lightVibrantSwatch.getPopulation();   tv1.setText("darkMutedColor");  tv1.setBackgroundColor(darkMutedColor);  tv2.setText("lightMutedColor");  tv2.setBackgroundColor(lightMutedColor);  tv3.setText("darkVibrantColor");  tv3.setBackgroundColor(darkVibrantColor);  tv4.setText("lightVibrantColor");  tv4.setBackgroundColor(lightVibrantColor);  tv5.setText("mutedColor");  tv5.setBackgroundColor(mutedColor);  tv6.setText("vibrantColor");  tv6.setBackgroundColor(vibrantColor);  } }); Copy the code

Palette + CardView

With this brief introduction, we have roughly cleared the Palette for what it will be, and now we can implement the Palette according to common requirements in development.

In the case of list page loading cards, it is common to add a translucent area at the bottom or top of the image to display text. The usual practice is to set a translucent color, but this will not work well on dark gray images. After Google provides Palette, it can analyze the most suitable background color according to the picture as the background color, so that the picture and the whole list can be displayed more gracefully.

The main content of this article is Palette, if you are not familiar with CardView, you can check the preceding:

1. Color samples

After creating a Palette instance, we also need to get a sample to be sampled (swatch). There are 6 swatches.

  • Palette.getVibrantSwatch()Return a vibrant sample class
  • Palette.getDarkVibrantSwatch()Returns a vivid (vibrant) dark tone sample class
  • Palette.getLightVibrantSwatch()Returns a sample class of bright (vibrant) tones
  • Palette.getMutedSwatch()Returns a soft sample class
  • Palette.getDarkMutedSwatch()Returns a soft dark tone sample class
  • Palette.getLightMutedSwatch()Returns a soft light tone sample class

2. Create vibrant sample classes

GetVibrantSwatch () is used to illustrate the six tones used in the sample. Practice the other tones yourself.

// Get a sample of a specific color
Palette.Swatch lightVibrantSwatch = palette.getVibrantSwatch();
if (lightVibrantSwatch == null) {
    for (Palette.Swatch swatch : palette.getSwatches()) {
        lightVibrantSwatch = swatch;
 break;  } } // Google recommended: the overall color of the picture RGB blend value -- the main hue int rgb = lightVibrantSwatch.getRgb(); // Google recommended: the color of the text in the middle of the image int bodyTextColor = lightVibrantSwatch.getBodyTextColor(); // Google recommended: as the title color (has a certain color value and image contrast) int titleTextColor = lightVibrantSwatch.getTitleTextColor(); Copy the code

Note:getVibrantSwatch()The Palette.Swatch object returned by the method could be null, so be sure to check for null or it might be thrownNullPointerExceptionThe exception.

3. Set the color transparency

When we get the RGB mixture value of the overall color of the picture, this value is the color closest to the picture, which is also the main color recommended by Google. In order to achieve the reduced effect mentioned above, the RGB value should be transparent before being used.

/ * * * @paramPercent of transparency * @paramRGB RGB values * @returnFinally set the color value of the opacity* /
protected int getTranslucentColor(float percent, int rgb) {  int blue = Color.blue(rgb);  int green = Color.green(rgb);  int red = Color.red(rgb);  int alpha = Color.alpha(rgb);  alpha = Math.round(alpha * percent);  return Color.argb(alpha, red, green, blue); } Copy the code

4. Load network images

Glide.asbitmap () method is used to load network pictures in the actual project. This method is implemented by using the third party library of an Adapter to prevent friends from seeing it. If you want to learn Adapter, please download the source code at the end of this article.


      
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/cardView"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_margin="5dp"  android:clickable="true"  android:focusable="true"  android:foreground="@drawable/item_touch_bg"  app:cardCornerRadius="1dp"  app:cardElevation="1dp"  app:cardPreventCornerOverlap="false"  app:cardUseCompatPadding="true">   <androidx.constraintlayout.widget.ConstraintLayout  android:layout_width="match_parent"  android:layout_height="wrap_content">   <ImageView  android:id="@+id/articleListImg"  android:layout_width="match_parent"  android:layout_height="200dp"  android:contentDescription="@null"  android:scaleType="centerCrop"  app:layout_constraintStart_toStartOf="parent"  app:layout_constraintTop_toTopOf="parent"  tools:src="@drawable/ic_launcher_background" />   <TextView  android:id="@+id/articleListTitle"  android:layout_width="match_parent"  android:layout_height="70dp"  android:gravity="center"  android:textColor="@color/white"  android:textSize="18dp"  android:textStyle="bold"  app:layout_constraintBottom_toBottomOf="@+id/articleListImg"  app:layout_constraintStart_toStartOf="parent" />   </androidx.constraintlayout.widget.ConstraintLayout>  </androidx.cardview.widget.CardView>  Copy the code
public class PaletteImageAdapter extends BaseCompatAdapter<ArticleBean.BaseViewHolder> {

    public PaletteImageAdapter(int layoutResId, List<ArticleBean> data) {
        super(layoutResId, data);
    }
  @Override  protected void convert(BaseViewHolder helper, ArticleBean item) {  // Use Glide.asbitmap () to convert  FutureTarget<Bitmap> bitmap = Glide.with(mContext)  .asBitmap()  .load(item.getImageUrl())  .submit();  // The color extraction task is performed in the child thread, and the color extraction from the Palette is a time-consuming operation depending on the image quality  new Thread(() -> {  try {  setPalette(bitmap.get(), helper, item);  } catch (Exception e) {  e.printStackTrace();  }  }).start();  }   private void setPalette(Bitmap bitmap, BaseViewHolder helper, ArticleBean item) {  Palette.from(bitmap).generate(new Palette.PaletteAsyncListener() {  @Override  public void onGenerated(@Nullable Palette palette) {  // Get a sample of a specific color  Palette.Swatch lightVibrantSwatch = palette.getVibrantSwatch();  if (lightVibrantSwatch == null) {  for (Palette.Swatch swatch : palette.getSwatches()) {  lightVibrantSwatch = swatch;  break;  }  }  // Google recommended: the overall color of the picture RGB blend value -- the main hue  int rgb = lightVibrantSwatch.getRgb();  // Google recommended: the color of the text in the middle of the image  int bodyTextColor = lightVibrantSwatch.getBodyTextColor();  // Google recommended: as the title color (has a certain color value and image contrast)  int titleTextColor = lightVibrantSwatch.getTitleTextColor();   helper.setText(R.id.articleListTitle, item.getTitle())  .setTextColor(R.id.articleListTitle, titleTextColor)  .setBackgroundColor(R.id.articleListTitle, getTranslucentColor(0.8 f, rgb));  ((ImageView) helper.getView(R.id.articleListImg)).setImageBitmap(bitmap);  }  });  } } Copy the code

Palette

As mentioned in the previous code comment, the Palette loading cannot be performed in the main thread, and an error will be reported if the image is displayed in a list. The task of extracting the image color from the Palette is time consuming, so it must be done in the child thread.

There are two loading modes: synchronous loading and asynchronous loading.

1. Synchronous loading

Because they are likely to be time consuming (analyzing large images or requiring more colors), they should not be performed in the main thread. You should first parse these two functions in another thread, and then use them after they are successfully parsed.

2. Asynchronous loading

Sometimes you won’t use the parsed color in the thread that loads the image (not the main thread), so the asynchronous methods in the Palette are provided, which differ from the previous ones in that the PaletteAsyncListener is passed in to provide a callback function when the image is parsed.

Source code download contains Material Design series control set, regularly updated, please look forward to!

Five, the summary

Many popular APP list screens now dynamically change the ToolBar’s color based on the content hue when swiping vertically, an effect that can be achieved by taking the image color from the Palette. In fact, Palette is not only suitable for the example I wrote, there are many applications of Palette, interested friends can learn more about it on the official website!

Thank you so much for reading this article! Your praise and comments are the biggest motivation for my creation!

My WeChat: Jaynm888

Programmer interview networking group: 764040616

Android programmers are cordially invited to join the wechat communication group. The public account can reply to the wechat group or add my wechat invitation to join the group.