220

In the new AppCompat library, we can tint the button this way:

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/follow"
    android:id="@+id/button_follow"
    android:backgroundTint="@color/blue_100"
    />

How can I set the tint of the button programmatically in my code? I'm basically trying to implement a conditional coloring of the button based on some user input.

Stephane Maarek
  • 5,202
  • 9
  • 46
  • 87
  • Are you sure android:backgroundTint is working on Pre-Lollipop? I test with both Button and ApCompatButton but backgroundTint only seems to be working on Lollipop. – Sharjeel Apr 23 '15 at 10:44
  • 1
    Please check [this answer](http://stackoverflow.com/a/36006440/2826147). – Amit Vaghela Mar 15 '16 at 08:53

23 Answers23

256

According to the documentation the related method to android:backgroundTint is setBackgroundTintList(ColorStateList list)

Update

Follow this link to know how create a Color State List Resource.

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:color="#your_color_here" />
</selector>

then load it using

setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.your_xml_name));

where contextInstance is an instance of a Context


using AppCompart

btnTag.setSupportButtonTintList(ContextCompat.getColorStateList(Activity.this, R.color.colorPrimary));
Dhaval Parmar
  • 18,812
  • 8
  • 82
  • 177
ColdFire
  • 6,764
  • 6
  • 35
  • 51
  • 2
    which is not a color, but a ColorStateList. How to leverage that? – Stephane Maarek Apr 22 '15 at 14:45
  • 9
    I get how to do it now thanks, but why would Android not allow you to just use a color manually? For every color of every button I have, I'll have to create an xml for a ColorStateList? That seems like a waste to me – Stephane Maarek Apr 22 '15 at 15:01
  • I haven't checked the source code to be able to answer that.. but if you're interested i'm sure u can find how they're handling that and find out why they did it this way.. i'm sure there is a reason behind it. – ColdFire Apr 22 '15 at 15:04
  • 4
    setBackgroundTintList needs API 21 even if you call it on AppCompatButton. – Sharjeel Apr 23 '15 at 11:20
  • Is it possible to use this on pre-Lollipop somehow? If so, for which kind of views? – android developer Jul 05 '15 at 10:21
  • getColorStateList(color) is now deprecated. You should add a theme as a second parameter, like: getColorStateList(color, theme). To add the currently used theme you can use `context.getTheme()`. Full code: `setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.your_xml_name, yourContext.getTheme()));` – Stefan Surkamp Nov 03 '15 at 16:16
  • or use ContextCompat like this : ContextCompat.getColorStateList(getContext(), R.color.your_xml_name) – gbero Jan 15 '16 at 14:00
  • 35
    The AppCompat support library offers a static helper: `ViewCompat.setBackgroundTintList(View, ColorStateList)` that can be used all the way back to API 4. But it only works for views that implement `TintableBackgroundView`, for example `AppCompatButton` (instead of the usual `Button`). – Jon Adams Mar 29 '16 at 20:42
  • 2
    Now, using `ViewCompat.setBackgroundTintList(View, ColorStateList)`, as @Jon Adams suggested, makes even more sense since View.setSupportButtonTintList is restricted with `RestrictTo` annotation. Details here: https://developer.android.com/reference/android/support/annotation/RestrictTo.html – AlexKost Nov 01 '17 at 07:10
121

You could use

button.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(R.id.blue_100)));

But I would recommend you to use a support library drawable tinting which just got released yesterday:

Drawable drawable = ...;

// Wrap the drawable so that future tinting calls work
// on pre-v21 devices. Always use the returned drawable.
drawable = DrawableCompat.wrap(drawable);

// We can now set a tint
DrawableCompat.setTint(drawable, Color.RED);
// ...or a tint list
DrawableCompat.setTintList(drawable, myColorStateList);
// ...and a different tint mode
DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_OVER);

You can find more in this blog post (see section "Drawable tinting")

dimsuz
  • 8,969
  • 8
  • 54
  • 88
86

Seems like views have own mechanics for tint management, so better will be put tint list:

ViewCompat.setBackgroundTintList(
    editText, 
    ColorStateList.valueOf(errorColor));
tse
  • 5,769
  • 6
  • 38
  • 58
38

here's how to do it in kotlin:

view.background.setTint(ContextCompat.getColor(context, textColor))
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38
28

In properly extending dimsuz's answer by providing a real code situation, see the following code snippet:

    Drawable buttonDrawable = button.getBackground();
    buttonDrawable = DrawableCompat.wrap(buttonDrawable);
    //the color is a direct color int and not a color resource
    DrawableCompat.setTint(buttonDrawable, Color.RED);
    button.setBackground(buttonDrawable);

This solution is for the scenario where a drawable is used as the button's background. It works on pre-Lollipop devices as well.

Shayne3000
  • 607
  • 8
  • 5
23

The simple way to do it

in Java

myButton.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(R.id.white)));

in Kotlin

myButton.setBackgroundTintList(ColorStateList.valueOf(resources.getColor(R.id.white)))
Osama Remlawi
  • 2,356
  • 20
  • 21
12

Have you tried something like this?

button.setBackgroundTintList(getResources().getColorStateList(R.id.blue_100));

note that getResources() will only work in an activity. But it can be called on every context too.

Chris K.
  • 1,060
  • 8
  • 10
8

this is easily handled in the new Material Button from material design library, first, add the dependency:

implementation 'com.google.android.material:material:1.1.0-alpha07'

then in your XML, use this for your button:

<com.google.android.material.button.MaterialButton
    android:id="@+id/accept"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/i_accept"
    android:textSize="18sp"
    app:backgroundTint="@color/grayBackground_500" />

and when you want to change the color, here's the code in Kotlin, It's not deprecated and it can be used prior to Android 21:

accept.backgroundTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, 
R.color.colorPrimary, theme))
Amin Keshavarzian
  • 3,646
  • 1
  • 37
  • 38
8

You can use something like that:

myButton.backgroundTintList = AppCompatResources.getColorStateList(context, R.color.primary_variant)
Gabriel TheCode
  • 163
  • 2
  • 8
7

You can use DrawableCompat e.g.

public static Drawable setTint(Drawable drawable, int color) {
    final Drawable newDrawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTint(newDrawable, color);
    return newDrawable;
}
mac229
  • 4,319
  • 5
  • 18
  • 24
7

The way I managed to get mine to work was by using CompoundButtonCompat.setButtonTintList(button, colour).

To my understanding this works regardless of android version.

Matt Jenje
  • 175
  • 1
  • 8
6

I had a similar problem. I wished to colour a complex drawable background for a view based on a color (int) value. I succeeded by using the code:

ColorStateList csl = new ColorStateList(new int[][]{{}}, new int[]{color});
textView.setBackgroundTintList(csl);

Where color is an int value representing the colour required. This represents the simple xml ColorStateList:

<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:color="color here"/>
</selector>

Hope this helps.

6

If you are using Kotlin and Material Design, you can change color of your MaterialButton like this:

myButton.background.setTintList(ContextCompat.getColorStateList(context, R.color.myColor))

You can improve it even better by creating an extension function for your MaterialButton in order to make you code more readable and your coding little more convenient:

fun MaterialButton.changeColor(color: Int) {
    this.background.setTintList(ContextCompat.getColorStateList(context, color))
}

Then, you can use your function everywhere like this:

myButton.changeColor(R.color.myColor)
Azizjon Kholmatov
  • 1,136
  • 1
  • 13
  • 26
4

For ImageButton you can use:

favoriteImageButton.setColorFilter(Color.argb(255, 255, 255, 255)); // White Tint
Saurabh Singh
  • 1,241
  • 13
  • 11
4

The suggested answer here doesn't work properly on android 5.0 if your XML based color state list references themed attributes.. For instance, I have an xml color state list like so:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="?colorPrimary" android:state_enabled="true"/>
    <item android:alpha="0.12" android:color="?attr/colorOnSurface"/>
</selector>

Using this as my backgroundTint from xml works just fine on android 5.0 and everything else. However if I try to set this in code like this:

(Don't do this)

myButton.setSupportButtonTintList(ContextCompat.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

It actually doesn't matter if I pass the Activity or the button's context to ContextCompat.getColorStateList() method, neither will give me the proper color state list with respect to the theme the button is within. This is because using theme attributes in color state lists wasn't supported until api 23 and ContextCompat does not do anything special to resolve these. Instead you must use AppCompatResources.getColorStateList() which does its own resource parsing/theme attribute resolution on devices < API 23.

Instead, you must use this:

myButton.setSupportBackgroundTintList(AppCompatResources.getColorStateList(myButton.getContext(), R.color.btn_tint_primary));

TLDR: use AppCompatResources and not -ContextCompat- if you'll need resolved themed resources across all API versions of android.

For more information on the topic, see this article.

Matt Wolfe
  • 8,924
  • 8
  • 60
  • 77
4

In addition to Shayne3000's answer you can also use a color resource (not only an int color). Kotlin version:

var indicatorViewDrawable = itemHolder.indicatorView.background
indicatorViewDrawable = DrawableCompat.wrap(indicatorViewDrawable)
val color = ResourcesCompat.getColor(context.resources, R.color.AppGreenColor, null) // get your color from resources
DrawableCompat.setTint(indicatorViewDrawable, color)
itemHolder.indicatorView.background = indicatorViewDrawable
coldembrace
  • 549
  • 8
  • 19
4

There are three options for it using setBackgroundTintList

int myColor = Color.BLACK;
  1. button.setBackgroundTintList(new ColorStateList(EMPTY, new int[] { myColor }));
  2. button.setBackgroundTintList(ColorStateList.valueOf(myColor));
  3. button.setBackgroundTintList(contextInstance.getResources().getColorStateList(R.color.my_color));
Ilya Gazman
  • 31,250
  • 24
  • 137
  • 216
3

If you dont want to care about different versions of android, you can use this code, for basicaly any view. Worked for me.

val states = arrayOf(intArrayOf(android.R.attr.state_enabled))
                    val colors = intArrayOf(Color.GREEN) // your color here
                    val colorStateList = ColorStateList(states, colors)
                  ViewCompat.setBackgroundTintList(yourButtonHere,colorStateList)

Kotlin version, wish a nice day to everyone reading this ;)

btw. if you created some drawable background shape this should override only only the tint color.

1
checkbox.ButtonTintList = ColorStateList.ValueOf(Android.Color.White);

Use ButtonTintList instead of BackgroundTintList

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Amit Malhi
  • 33
  • 5
1

Tint can be added to button like:

filterBtn.setBackgroundTintList(ContextCompat.getColorStateList(context,R.color.colorPrimary))
Muhammad Saqlain
  • 2,112
  • 4
  • 33
  • 48
Azade Rahmati
  • 135
  • 1
  • 5
0

simple we can also use for an imageview

    imageView.setColorFilter(ContextCompat.getColor(context,
R.color.COLOR_YOUR_COLOR));
Raj008
  • 3,539
  • 2
  • 28
  • 26
0

If anyone wants to know how to set the HTML color code in the background tint (in my case the color code is coming from backend)

String htmlColorCode = "#FF0000";
int colorInt = Color.parseColor(htmlColorCode);
View myView = findViewById(R.id.my_view);
ViewCompat.setBackgroundTintList(myView, ColorStateList.valueOf(colorInt));
BornToCode
  • 44
  • 1
  • 7
-1

With Kotlin,

checkbox.buttonTintList = AppCompatResources.getColorStateList(context, color.colorPrimary)
Krishan Madushanka
  • 319
  • 1
  • 5
  • 21