188

I'm trying to change the color on a white marker image by code. I have read that the code below should change the color, but my marker remains white.

Drawable.setColorFilter( 0xffff0000, Mode.MULTIPLY )

Did I miss something? Is there any other way to change colors on my drawables located in my res folder?

Johan
  • 34,157
  • 52
  • 174
  • 280
  • accepted answer didn't work for me..used this [answer][1], [1]: http://stackoverflow.com/questions/5940825/android-change-shape-color-in-runtime – sham.y Jan 16 '15 at 15:10
  • I think all the answers here change the background color, but not color of the image. Im i right? can anyone tell me please? I tried all the solutions here and also on same questions on stackoverflow, but they change only background color in may case. So i think, we can only change background color, but not the images color. I'm I right? – Shirish Herwade Apr 20 '15 at 12:44
  • Check this answer: https://stackoverflow.com/a/66479081/3503855 – Anis LOUNIS Mar 05 '21 at 17:49

20 Answers20

325

Try this:

Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, R.drawable.my_drawable); 
Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
DrawableCompat.setTint(wrappedDrawable, Color.RED);    

Using DrawableCompat is important because it provides backwards compatibility and bug fixes on API 22 devices and earlier.

Alex Lockwood
  • 82,434
  • 38
  • 201
  • 248
ρяσѕρєя K
  • 130,641
  • 51
  • 193
  • 212
  • Hmm, the color remains white. Could it have to do with the hello mapview `OverlayItems` class that might be causing the problem? Its a regular drawable from my res folder, nothing special... – Johan Jul 07 '12 at 16:27
  • @ρяσѕρєяK you are very awesome.very helpful – luttu android Oct 15 '13 at 12:59
  • 31
    You might prefer PorterDuff.Mode.SRC_IN if you want it to work with a wider range of source colors. – Lorne Laliberte Jul 16 '15 at 19:27
  • PorterDuff.Mode.MULTIPLY did not changed anything for me ( Black star with transparent background). i used the PorterDuff.Mode.SRC_ATOP for coloring the actual bitmap. – Viktor Petrovski Mar 09 '16 at 11:54
  • There's also a convenience method you can use: `setColorFilter(Color.WHITE, PorterDuff.Mode.SRC_IN)` – CorayThan Feb 08 '17 at 00:25
  • 1
    PorterDuffColorFilter constructor takes ARGB color format – RichX Mar 23 '17 at 09:31
  • 3
    will be interesting to mutate the drawable with #mutate() to avoid share its state with any other drawable, otherwise if you reuse the drawable could have wrong color. – Ricard Mar 27 '20 at 18:02
  • The drawables are shared amongst all getDrawable from resources, hence the mutate() call is required to be able to change the tint of a drawable, without altering all the drawables associates with that resource ID, see https://stackoverflow.com/a/44593641/5555218 – Ricard Sep 18 '20 at 09:55
154

You can try this for svg vector drawable

DrawableCompat.setTint(
    DrawableCompat.wrap(myImageView.getDrawable()),
    ContextCompat.getColor(context, R.color.another_nice_color)
);
Alex Lockwood
  • 82,434
  • 38
  • 201
  • 248
amorenew
  • 10,432
  • 9
  • 43
  • 65
  • 7
    Best way I've seen for svg. – apSTRK Jan 18 '17 at 21:44
  • 1
    prefer this over the accepted answer, although both will work, but with this one I don't have to worry about what drawable to set, i just get the one already there, and it's also backward compatible, great! – usernotnull Jun 29 '17 at 20:17
  • 1
    Best answer when nothing worked iot work like a charm! Thanks a lot! Note: It also works for when you have a xml drawable in your imageView/AppCompatImageView – Sjd Sep 15 '17 at 13:10
  • 1
    How to remove it programatically ? – Hardik Joshi Oct 04 '18 at 09:04
  • 3
    @HardikJoshi Documentation says: *To clear the tint, pass `null` to `Drawable#setTintList(ColorStateList)`* – arekolek Jan 11 '19 at 15:55
  • Unfortunately, this overrides the set stroke in the xml file, whereas the color filter option doesn't – Big_Chair May 12 '19 at 11:01
  • 1
    Correction, it only does so when not setting a mode. When using `DrawableCompat.setTintMode(bgDrawable, PorterDuff.Mode.MULTIPLY)` before applying the tint, it works the same as color filter. – Big_Chair May 12 '19 at 11:08
  • Remember to use `mutate()` or else you'd change the colour of the drawable globally! – ericn Jul 07 '21 at 15:07
35

You may need to call mutate() on the drawable or else all icons are affected.

Drawable icon = ContextCompat.getDrawable(getContext(), R.drawable.ic_my_icon).mutate();
TypedValue typedValue = new TypedValue();
getContext().getTheme().resolveAttribute(R.attr.colorIcon, typedValue, true);
icon.setColorFilter(typedValue.data, PorterDuff.Mode.SRC_ATOP);
shicky
  • 1,095
  • 11
  • 20
31

You can try this for ImageView. using setColorFilter().

imageView.setColorFilter(ContextCompat.getColor(context, R.color.colorWhite));
Jaydip Meghapara
  • 1,969
  • 1
  • 14
  • 14
22

Another way to do this on Lollipop, android 5.+ is setting a tint on a bitmap drawable like such:

<?xml version="1.0" encoding="utf-8"?>
<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_back"
    android:tint="@color/red_tint"/>

This will work for you if you have a limited number of colors you want to use on your drawables. Check out my blog post for more information.

MinceMan
  • 7,414
  • 3
  • 36
  • 40
  • 2
    Nice! Btw, this seems to work fine on pre-Lollipop too. (Just tested this with `minSdkVersion 16` and Android 4.1.1 device.) – Jonik Mar 03 '15 at 12:16
  • When creating a bitmap this way, it does not stretch to fit the layout as it would when using `android:background="..."`. Pretty strange! – Prince May 19 '15 at 10:45
  • I think that's because you are not creating a nine patch here. – MinceMan May 19 '15 at 12:39
  • Sorry this page does not exist =( – Linh Jul 29 '16 at 07:41
  • @Jonik The answers in your provided question are irrelevant. This question is asking for the way to change *Drawable*'s colour, not ImageView. – Antony.H Feb 02 '17 at 04:45
13

I have wrote a generic function in which you can pass context, icon is id drawable/mipmap image icon and new color which you need for that icon.

This function returns a drawable.

public static Drawable changeDrawableColor(Context context,int icon, int newColor) {
    Drawable mDrawable = ContextCompat.getDrawable(context, icon).mutate(); 
    mDrawable.setColorFilter(new PorterDuffColorFilter(newColor, PorterDuff.Mode.SRC_IN)); 
    return mDrawable;
} 

changeDrawableColor(getContext(),R.mipmap.ic_action_tune, Color.WHITE);
Sachin Tanpure
  • 800
  • 8
  • 11
10

You could try a ColorMatrixColorFilter, since your key color is white:

// Assuming "color" is your target color
float r = Color.red(color) / 255f;
float g = Color.green(color) / 255f;
float b = Color.blue(color) / 255f;

ColorMatrix cm = new ColorMatrix(new float[] {
        // Change red channel
        r, 0, 0, 0, 0,
        // Change green channel
        0, g, 0, 0, 0,
        // Change blue channel
        0, 0, b, 0, 0,
        // Keep alpha channel
        0, 0, 0, 1, 0,
});
ColorMatrixColorFilter cf = new ColorMatrixColorFilter(cm);
myDrawable.setColorFilter(cf);
JJD
  • 47,369
  • 53
  • 194
  • 328
tiguchi
  • 5,362
  • 1
  • 31
  • 39
9

This worked for me. Make sure to put "ff" between 0x and color code. Like this 0xff2196F3

Drawable mDrawable = ContextCompat.getDrawable(MainActivity.this,R.drawable.ic_vector_home);
                    mDrawable.setColorFilter(new
                            PorterDuffColorFilter(0xff2196F3,PorterDuff.Mode.SRC_IN));
Bek
  • 6,295
  • 4
  • 16
  • 31
  • Hi @Bek welcome to stackoverflow. If this worked for you, it would be very helpful to include a jsfiddle with minimal solution to show that. It will help the person who posted question to understand properly. – Arjun Chaudhary Nov 15 '17 at 04:21
6

Same as the accepted answer but a simpler convenience method:

val myDrawable = ContextCompat.getDrawable(context, R.drawable.my_drawable)
myDrawable.setColorFilter(Color.GREEN, PorterDuff.Mode.SRC_IN)
setCompoundDrawablesWithIntrinsicBounds(myDrawable, null, null, null)

Note, the code here is Kotlin.

CorayThan
  • 16,067
  • 27
  • 106
  • 154
4

Use this: For java

view.getBackground().setColorFilter(Color.parseColor("#343434"), PorterDuff.Mode.SRC_OVER)

for Kotlin

view.background.setColorFilter(Color.parseColor("#343434"),PorterDuff.Mode.SRC_OVER)

you can use PorterDuff.Mode.SRC_ATOP, if your background has rounded corners etc.

Ravi.Dudi
  • 1,218
  • 12
  • 11
4

For those who use Kotlin a simple extension function:

fun Drawable.tint(context: Context,  @ColorRes color: Int) {
    DrawableCompat.setTint(this, context.resources.getColor(color, context.theme))
}

and then simply do

background.tint(context, R.color.colorPrimary)
Chapz
  • 555
  • 6
  • 12
3

You may want to try Mode.LIGHTEN or Mode.DARKEN. The Android Javadocs are horrible at explaining what the PorterDuff Modes do. You can take a look at them here: PorterDuff | Android

I suggest looking around at Compositing on Mozilla's site here. (They don't have all the modes that android does but they have a lot of them)

groovecoder
  • 1,475
  • 17
  • 27
sebsebmc
  • 112
  • 4
2

Syntax

"your image name".setColorFilter("your context".getResources().getColor("color name"));

Example

myImage.setColorFilter(mContext.getResources().getColor(R.color.deep_blue_new));
ArteFact
  • 480
  • 3
  • 13
2

You can change your drawable color in this way:

background = view.findViewById(R.id.background)

val uDrawable = AppCompatResources.getDrawable(view.context, R.drawable.background)
uDrawable?.let {
      val wDrawable = DrawableCompat.wrap(it)
      DrawableCompat.setTint(wDrawable, ContextCompat.getColor(view.context, 
                                                      color /*specify your int color code*/))
      background.background = wDrawable
}
Ali Azaz Alam
  • 1,682
  • 1
  • 15
  • 27
2

SDK >= 21 one line myIconImageView.getDrawable().setTint(getResources().getColor(myColor))

close_file
  • 181
  • 1
  • 4
  • Pretty nice, I recommend to use `Drawable newDrawable = myDrawable.mutate().setTint(getResources().getColor(myColor))` to avoid changing it globally – FreddaP Mar 03 '22 at 14:01
1

Kotlin Version

val unwrappedDrawable =
            AppCompatResources.getDrawable(this, R.drawable.your_drawable)
        val wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable!!)
DrawableCompat.setTint(wrappedDrawable, Color.RED)
0

This is what i did:

public static Drawable changeDrawableColor(int drawableRes, int colorRes, Context context) {
    //Convert drawable res to bitmap
    final Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), drawableRes);
    final Bitmap resultBitmap = Bitmap.createBitmap(bitmap, 0, 0,
            bitmap.getWidth() - 1, bitmap.getHeight() - 1);
    final Paint p = new Paint();
    final Canvas canvas = new Canvas(resultBitmap);
    canvas.drawBitmap(resultBitmap, 0, 0, p);

    //Create new drawable based on bitmap
    final Drawable drawable = new BitmapDrawable(context.getResources(), resultBitmap);
    drawable.setColorFilter(new
            PorterDuffColorFilter(context.getResources().getColor(colorRes), PorterDuff.Mode.MULTIPLY));
    return drawable;
}
Edwin
  • 360
  • 4
  • 13
0

Create Method like this :

//CHANGE ICON COLOR
private void changeIconColor(Context context ,int drawable){
    Drawable unwrappedDrawable = AppCompatResources.getDrawable(context, drawable);
    assert unwrappedDrawable != null;
    Drawable wrappedDrawable = DrawableCompat.wrap(unwrappedDrawable);
    DrawableCompat.setTint(wrappedDrawable, getResources().getColor(R.color.colorAccent));
}

and use it like it :

    changeIconColor(this,R.drawable.ic_home);
Sana Ebadi
  • 5,750
  • 1
  • 38
  • 42
0

Easiest Way to do it :

imageView.setColorFilter(Color.rgb(r, g b));

or

imageView.setColorFilter(Color.argb(a, r, g, b));

a, r, g, b : Color argb values.

Anubhav
  • 1,676
  • 20
  • 14
0

Long story short :

public void changeDrawableColor(Drawable drawable,int color){
    drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}

public Drawable getColoredDrawable(@DrawableRes int resid,int color){
    Drawable drawable= ContextCompat.getDrawable(context, resid).mutate();
    drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
    return drawable;
}
ucMedia
  • 3,221
  • 4
  • 32
  • 42