time

Placing text with appropriate color over image in Android

When Android 5.0 (Lollipop) version was released, support library v7 was also updated with a new library called Android Palette library. This new library can help you to pick colors from an image dynamically. For example if you are building an image intensive app, where user experience is of prime importance you can use this Android Palette library to extract colors from the image on screen. Further these colors could be used at prominent spaces on your screen to blend the image into your app screen.

First, include the Palette library in your build.gradle file:

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

As the name suggests Android Palette is a collection of swatches. Each Android Swatch represents a color. When an image is used to generate a palate we can optionally specify the number of swatches we want from that image. In case we don’t specify the number, 16 swatches would be returned. Although the most prominently used swatches are given a name:

  • Vibrant – use Palette.getVibrantSwatch() method to get this swatch.
  • Vibrant dark – use Palette.getDarkVibrantSwatch() method to get this swatch.
  • Vibrant light – use Palette.getLightVibrantSwatch() method to get this swatch.
  • Muted – use Palette.getMutedSwatch() method to get this swatch.
  • Muted dark – use Palette.getDarkMutedSwatch() method to get this swatch.
  • Muted light – use Palette.getLightMutedSwatch() method to get this swatch.

If you wish to retrieve all the swatches, you can do it by using this piece of code:

List<Palette.Swatch> swatches = palette.getSwatches();

Some of the important methods of the Android Swatch class are:

  • getRgb() – Returns the color in RGB value.
  • getTitleTextColor() – Returns the title color in RGB value. A color in contrast with the swatch color, safe to use on top of swatch as title text color.
  • getBodyTextColor() – Returns the body text color in RGB value. A color in contrast with the swatch color, safe to use on top of swatch as body text color.
  • getPopulation() – Returns the quantity of pixels represented by this swatch.

You can change the color of the TextView according to the colors of the ImageView via Palette API from the Support Library. You can extract the prominent colors from an image and set the appropriate color on an overlaid TextView.

The code in following listing shows how to use the Palette API to perform an asynchronous operation on a Bitmap and using the result to set the color on a TextView.

public class MainActivity extends AppCompatActivity {
    TextView tv;
    ImageView iv;

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

        tv = (TextView) findViewById(R.id.tv);
        iv = (ImageView) findViewById(R.id.iv);
        Bitmap bitmap = ((BitmapDrawable) iv.getDrawable()).getBitmap();
        setTextColorForImage(tv, bitmap);
    }

    private void setTextColorForImage(final TextView textView, Bitmap firstPhoto) {
        Palette.from(firstPhoto)
            .generate(new Palette.PaletteAsyncListener() {
                @Override
                public void onGenerated(Palette palette) {
                    Palette.Swatch swatch = palette.getVibrantSwatch();
                    if (swatch == null && palette.getSwatches().size() > 0) {
                        swatch = palette.getSwatches().get(0);
                    }

                    int titleTextColor = Color.WHITE;

                    if (swatch != null) {
                        titleTextColor = swatch.getTitleTextColor();
                        //titleTextColor = ColorUtils.setAlphaComponent(titleTextColor, 255);
                    }
                    textView.setTextColor(titleTextColor);

                    ActionBar actionBar = getSupportActionBar();
                    if (actionBar != null) {
                        int muted = palette.getMutedColor(getResources().getColor(R.color.colorAccent));

                        actionBar.setDisplayHomeAsUpEnabled(true);
                        //set color action bar
                        actionBar.setBackgroundDrawable(new ColorDrawable(muted));

                        //set color status bar
                        getWindow().setStatusBarColor(muted);
                    }
                }
            });
    }
}

In the preceding method we perform an asynchronous calculation using the Palette API to get the vibrant color we want to use for the TextView. The default behavior is that the color will be translucent, and if we want to disable that we need to use ColorUtils.setAlphaComponent() to make the color opaque. Also, the prceding code has two fallbacks; if the vibrant color isn’t available we get the first swatch from the ones that are. If we still didn’t get a swatch we default to the color white.

Result

android_palette_api.png