One of the defining features of material design is the use of color to compliment and emphasize content on the screen. Using the Palette
class, developers can extract prominent colors from a bitmap for use in their apps to customize user interface elements.
In this article, you will learn how to create a Palette
object from a bitmap. Contained within each Palette
is a set of Swatch
objects that will allow you to work with specific color profiles and a list of visible colors from the image.
1. Creating a Palette
To get started, you will need to import the palette support library into your project by including the following line in the dependencies node of your project's build.gradle file. Since this is a v7 support library, the Palette
related classes are available back to Android API 7.
compile 'com.android.support:palette-v7:+'
After running a gradle sync on your project, you are able to generate a Palette
from a bitmap. This can be done using the Palette.Builder
either synchronously by calling the generate()
method without any parameters, or asynchronously by calling generate(Palette.PaletteAsyncListener listener)
. Because it can take time to create the Palette
, it is recommended that the synchronous method only be called from a background thread. In addition to the two generate methods, the Palette.Builder
class has a couple of other useful methods that come with their own trade-offs:
maximumColorCount(int numOfSwatches)
allows you to change how manySwatch
objects should be generated from the bitmap. The default for the builder is 16. The moreSwatch
objects you generate, the longer it will take to generate thePalette
.resizeBitmapSize(int maxDimension)
resizes the bitmap so that its largest dimension will only be as large as the passed value of this method. The larger your bitmap, the longer it will take to generate aPalette
. Likewise, smaller bitmaps will process faster, but you will lose out on color precision.
The following code snippet shows how to create a bitmap from a local resource and asynchronously create a Palette
object.
Bitmap bitmap = BitmapFactory.decodeResource( getResources(), R.drawable.union_station ); Palette.from( bitmap ).generate( new Palette.PaletteAsyncListener() { @Override public void onGenerated( Palette palette ) { //work with the palette here } });
Once you have a Palette
, you can begin working with the associated Swatch
objects.
2. Swatches
Swatch
objects represent colors generated from an image's palette. Each Swatch
contains:
- an RGB (Red, Green, Blue) and HSL (Hue, Saturation, Lightness) value for a color.
- a population value reflecting the number of pixels represented by the
Swatch
. - a color value that can be used for title text when displayed on the
Swatch
's primary color. - a color value that can be used for a body of text when displayed on the
Swatch
's primary color.
Swatch Profiles
Each Palette
has a set of six predefined color profiles:
- vibrant
- light vibrant
- dark vibrant
- muted
- light muted
- dark muted
While each of these can be useful depending on your app design, vibrant and dark vibrant are the most commonly used. One thing to note is that any of these profiles may be null
, so you should handle this situation accordingly. In the sample project, in the onGenerated(Palette palette)
method from the asynchronous Palette.Builder
, you can see how to extract each profile Swatch
.
setViewSwatch( mVibrantTextView, palette.getVibrantSwatch() ); setViewSwatch( mLightVibrantTextView, palette.getLightVibrantSwatch() ); setViewSwatch( mDarkVibrantTextView, palette.getDarkVibrantSwatch() ); setViewSwatch( mMutedTextView, palette.getMutedSwatch() ); setViewSwatch( mLightMutedTextView, palette.getLightMutedSwatch() ); setViewSwatch( mDarkMutedTextView, palette.getDarkMutedSwatch() );
setViewSwatch(TextView view, Palette.Swatch swatch)
is a method that accepts a Swatch
and TextView
, and sets the TextView
background and text colors from values in the Swatch
. You'll notice that we first check to see if the Swatch
is null
and, if it is, we simply hide the view.
public void setViewSwatch( TextView view, Palette.Swatch swatch ) { if( swatch != null ) { view.setTextColor( swatch.getTitleTextColor() ); view.setBackgroundColor( swatch.getRgb() ); view.setVisibility( View.VISIBLE ); } else { view.setVisibility( View.GONE ); } }
Additional Swatches
In addition to the standard profile Swatch
objects, each Palette
contains a list of general Swatch
objects generated from the bitmap. These can be retrieved from the Palette
as a List
by using the getSwatches()
method.
In the sample project, this List
is retrieved and placed into an ArrayAdapter<Palette.Swatch>
that then displays the Swatch
primary color and body text color, as well as the number of pixels represented in the bitmap by this Swatch
. One thing to pay attention to is that the list is not in any particular order. In the sample project, I have sorted the items by their population value.
for( Palette.Swatch swatch : palette.getSwatches() ) { mAdapter.add( swatch ); } mAdapter.sortSwatches(); mAdapter.notifyDataSetChanged();
In this code snippet, mAdapter
is the adapter of Swatch
objects with the following methods:
@Override public View getView( int position, View convertView, ViewGroup parent ) { ViewHolder holder; if( convertView == null ) { holder = new ViewHolder(); convertView = LayoutInflater.from( getContext() ).inflate( R.layout.color_item, parent, false ); holder.view = (TextView) convertView.findViewById( R.id.view ); convertView.setTag( holder ); } else { holder = (ViewHolder) convertView.getTag(); } holder.view.setBackgroundColor( getItem( position ).getRgb() ); holder.view.setTextColor( getItem( position ).getBodyTextColor() ); holder.view.setText( "Population: " + getItem( position ).getPopulation() ); return convertView; } public void sortSwatches() { sort(new Comparator<Palette.Swatch>() { @Override public int compare( Palette.Swatch lhs, Palette.Swatch rhs ) { return rhs.getPopulation() - lhs.getPopulation(); } }); } public class ViewHolder { TextView view; }
Conclusion
In this article, you have learned about the Palette
support library and how to extract swatches of color from a bitmap. This will allow you to customize your user interface elements, such as backgrounds and text, so that they compliment images within your app. When coupled with the Color
and ColorUtil
classes (available in the v4 support library), you have even more options available for the colorization of your app.