How to use selector to tint ImageView? How to use selector to tint ImageView? android android

How to use selector to tint ImageView?


If you're in API 21+ you can do this easily in XML with a selector and tint:

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_activated="true">        <bitmap android:src="@drawable/ic_settings_grey"                android:tint="@color/primary" />    </item>    <item android:drawable="@drawable/ic_settings_grey"/></selector>


I implemented this using DrawableCompat from the Android support-v4 library.

With a regular ImageButton (which subclasses ImageView, so this info also applies to ImageViews), using a black icon from the material icons collection:

<ImageButton  android:id="@+id/button_add"  android:src="@drawable/ic_add_black_36dp"  android:background="?attr/selectableItemBackgroundBorderless"  android:contentDescription="@string/title_add_item" />

This is the utility method I created:

public static void tintButton(@NonNull ImageButton button) {    ColorStateList colours = button.getResources()            .getColorStateList(R.color.button_colour);    Drawable d = DrawableCompat.wrap(button.getDrawable());    DrawableCompat.setTintList(d, colours);    button.setImageDrawable(d);}

Where res/color/button_colour.xml is a selector that changes the icon colour from red to semi-transparent red when the button is pressed:

<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android">    <item      android:state_pressed="false"      android:color="@color/red" />    <item      android:color="@color/red_alpha_50pc" /></selector>

After the ImageButton has been inflated in my activity's onCreate() method, I just call the tintButton(...) helper method once for each button.


I have tested this on Android 4.1 (my minSdkVersion) and 5.0 devices, but DrawableCompat should work back to Android 1.6.


In reference to my solution at https://stackoverflow.com/a/18724834/2136792, there are a few things you're missing:

TintableImageView.java

@Overrideprotected void drawableStateChanged() {    super.drawableStateChanged();    if (tint != null && tint.isStateful())        updateTintColor();}public void setColorFilter(ColorStateList tint) {    this.tint = tint;    super.setColorFilter(tint.getColorForState(getDrawableState(), 0));}private void updateTintColor() {    int color = tint.getColorForState(getDrawableState(), 0);    setColorFilter(color);}

drawableStateChanged() must be overridden for the tint to be updated when the element's state changes.

I'm not sure if referencing a drawable from a drawable might cause an issue, but you can simply move your selector.xml into a folder "/res/color" to reference it with "@color/selector.xml" (aapt merges both /res/values/colors.xml and the /res/color folder).