Android Button Drawable Tint

63,421

Solution 1

You can achieve coloring the drawableleft on a button with this method:

Step 1: Create a drawable resource file with bitmap as parent element as shown below and name it as ic_action_landscape.xml under the drawable folder

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

Step 2: Create your Button control in your layout as below

<Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:backgroundTint="@color/md_light_green_500"
        android:drawableLeft="@drawable/ic_action_landscape"
        android:drawablePadding="8dp"
        android:fontFamily="sans-serif"
        android:gravity="left|center_vertical"
        android:stateListAnimator="@null"
        android:text="@string/drawer_quizzes"
        android:textColor="#fff"
        android:textSize="12dp" />

The button gets the drawable from the ic_action_landscape.xml from the drawable folder instead of @android:drawable or drawable png(s).

Method 2:
Step 1:
You can even add the icon as a Action Bar and Tab icons with Foreground as Image that can be imported from a custom location or a Clipart

Step 2:
Under Theme dropdown select Custom

Step 3:
Then select the color as #FFFFFF in the Foreground color selection. Method 2 Pictorial representation

Finally finish the wizard to add the image, then add the drawable as an image.

Pictorial representation for answer to the question

Solution 2

You can either use drawable filter or if your API>=M then you can simply

textView.compoundDrawableTintList = ColorStateList.valueOf(Color.WHITE)

or in XML,

android:drawableTint="@color/white"

Solution 3

I know there are lots of answers already, but non of them made me happy since I didn't want to have different drawables for different styles of elements.

So my solution was to set color filter in constructor like this:

int textColor = getTextColors().getColorForState(EMPTY_STATE_SET, Color.WHITE);
Drawable[] drawables = getCompoundDrawablesRelative();
for (Drawable drawable : drawables) {
    if (drawable != null) {
        drawable.setColorFilter(textColor, PorterDuff.Mode.SRC_ATOP);
    }
}

I used text color because this was what I need, but it can be replaced with custom attribute to be more dinamic.

Solution 4

I was able to accomplish this same exact thing using a MaterialButton (from the material support library, which most people are probably using already). MaterialButton has an attribute named icon which can be placed left/center/right (default left). It also has an attribute called iconTint which will tint the icon.

Gradle:

implementation "com.google.android.material:material:1.1.0-alpha09"

View:

<com.google.android.material.button.MaterialButton
    android:layout_width="0dp"
    android:layout_weight="1"
    android:text="@string/drawer_quizzes"
    android:backgroundTint="@color/md_light_green_500"
    android:stateListAnimator="@null"
    android:textColor="#fff"
    android:textSize="12dp"
    android:fontFamily="sans-serif"
    app:icon="@drawable/ic_action_landscape"
    app:iconTint="@color/white"
    android:gravity="left|center_vertical"
    android:drawablePadding="8dp"
    />

Solution 5

As @Boris suggested, you can use the support library.

I have extended the AppCompatButton with some draft code. The TintAppCompatButton should have default behaviour but TintAppCompatButtonCustom was made to demo custom coloring.

I’ll see if I can raise a PR to get that into the official support library.

The code of interest is:

private void init() {
    PorterDuff.Mode tintMode = PorterDuff.Mode.SRC_IN;
    Drawable[] ds = getCompoundDrawables();
    tint(ds[LEFT], Color.RED, tintMode);
    tint(ds[TOP], Color.YELLOW, tintMode);
    tint(ds[RIGHT], Color.GREEN, tintMode);
    tint(ds[BOTTOM], Color.BLUE, tintMode);
}

private void tint(Drawable d, int color, PorterDuff.Mode tintMode) {
    TintInfo ti = new TintInfo();
    ti.mTintMode = tintMode;
    ti.mTintList = ColorStateList.valueOf(color);
    ti.mHasTintList = true;
    ti.mHasTintMode = true;

    TintManager.tintDrawable(d, ti, new int[]{0});
}
Share:
63,421

Related videos on Youtube

vigonotion
Author by

vigonotion

Updated on July 09, 2022

Comments

  • vigonotion
    vigonotion almost 2 years

    Is it possible to tint the drawableLeft in an android button? I have a black drawable I'd like to tint white. I know how to achieve this with an image view (image on the left) but I want to do this with the default android button.

    enter image description here

    My source code:

    <Button android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:text="@string/drawer_quizzes"
            android:backgroundTint="@color/md_light_green_500"
            android:stateListAnimator="@null"
            android:textColor="#fff"
            android:textSize="12dp"
            android:fontFamily="sans-serif"
            android:drawableLeft="@drawable/ic_action_landscape"
            android:gravity="left|center_vertical"
            android:drawablePadding="8dp"
            />
    

    Is there any way to tint the button? Or is there a custom view method to achieve this effect?

    • Hawraa Khalil
      Hawraa Khalil almost 9 years
      so you want to place an image on the left of the text in the button?
    • vigonotion
      vigonotion almost 9 years
      @HawraaKhalil yes, exactly. But it should be tinted white
    • DarkLeafyGreen
      DarkLeafyGreen about 7 years
      Vote here code.google.com/p/android/issues/detail?id=198613 if you want drawableTint to go into support library
  • vigonotion
    vigonotion almost 9 years
    Thanks, i'm using the first method now as I'd also like to use the (black) icon in other parts of the ui.
  • Boris
    Boris over 8 years
    Keep in mind though, that the tint attribute is only supported since Lollipop. For pre-Lollipop support, I used the following code to tint the button drawable programmatically: Drawable[] drawables = postButton.getCompoundDrawables(); Drawable wrapDrawable = DrawableCompat.wrap(drawables[0]); DrawableCompat.setTint(wrapDrawable, getResources().getColor(android.R.color.white));, using the support-v4 library.
  • vida
    vida about 8 years
    It seems method 1 only works for default icons(from android). If we add a new icon on our resources, it does not work on my end. Just a note.
  • Nitesh Pareek
    Nitesh Pareek almost 8 years
    android:backgroundTint="@color/md_light_green_500" its only above api level 23 not work in lolipop
  • ban-geoengineering
    ban-geoengineering over 7 years
    This (method 1, in my case) also works if you want to change the drawable colour for a TextView.
  • Shadab K
    Shadab K about 7 years
    What is the problem you are facing @AnandSavjani? Let me see if I can assist you and make my answer better.
  • Anand Savjani
    Anand Savjani about 7 years
    I am trying to set drawable tint but its now showing any tint effect
  • Harminder Singh
    Harminder Singh over 5 years
    what about below 23??
  • Jimit Patel
    Jimit Patel almost 5 years
    Thats nice hack. My app's minimum version is 21 so don't have to worry about below 21
  • algorhythm
    algorhythm over 4 years
    android:drawableTint is the correct answer here. Thanks!
  • Kishan Solanki
    Kishan Solanki about 4 years
    for that you can use app:drawableTint
  • Shadab K
    Shadab K almost 3 years
    Thank you @JimitPatel
  • Starwave
    Starwave over 2 years
    Weird, doesn't work for me in API 23.
  • Daniel  Luche
    Daniel Luche over 2 years
    @KishanSolanki, here doens't work in API 23