Drawable tinting for api <21
Asked Answered
C

10

85

Is it possible to make drawable tinting work for api < 21?

<bitmap
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:src="@drawable/ic_calendar"
    android:tint="@color/primary" />

Works just fine but only for devices with API21. Any workaround for lower api devices or AppCompat support? Can't find anything.

Corley answered 19/3, 2015 at 21:37 Comment(0)
C
111

Use the AppCompatImageView like so:

<android.support.v7.widget.AppCompatImageView
        android:id="@+id/my_appcompat_imageview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/my_image"
        android:tint="#636363"
    />

Make sure you have the latest appcompat-v7 in your app's build.gradle.

Example: compile 'com.android.support:appcompat-v7:25.0.0' in your app's build.gradle.

Cirenaica answered 16/5, 2016 at 19:6 Comment(6)
From AppCompatImageView docs: This will automatically be used when you use ImageView in your layouts. You should only need to manually use this class when writing custom views. developer.android.com/reference/android/support/v7/widget/… So, using the normal ImageView in the layout should work just fine.Rohn
As @NimrodDayan mentioned above, this shouldn't be necessary. I am getting reports of android:tint not working on a Samsung A5 and Moto G, however (using appcompat-v7:23.4.0), so it's possible ImageViews aren't being replaced properly on some devices.Koumis
@StephenKidson, I'm using the same version of appcompat and also bumped into the same issue on an unknown brand device. Did you manage to solve this? I wonder if there's bug reported about this...Rohn
@NimrodDayan worked around it by making a separate drawable XML for the color I was tinting to - not ideal but pretty much the only way to ensure the issue was resolved without getting ahold of each affected device.Koumis
This did not work on emulator Android 4.0 using appcompat-v7:25.1.0.Seymore
AppCompatImageView cannot be used inside a Widget. Use setColorFilter on the ImageView.Deficiency
R
46

You can achieve that using source code. Previously tinting was not supported by DrawableCompat. Starting from support library 22.1 you can do that, but you need do it in this way:

Drawable normalDrawable = getResources().getDrawable(R.drawable.drawable_to_tint);
Drawable wrapDrawable = DrawableCompat.wrap(normalDrawable);
DrawableCompat.setTint(wrapDrawable, getResources().getColor(R.color.colorPrimaryLight));
Repress answered 28/2, 2017 at 9:43 Comment(1)
If you need to support tinting on < 21 APIs, then you probably want to use ContextCompat.getColor() instead of getResources().getColor().Riane
H
22

Couldn't you simply use an ImageView to display your Drawable? android:tint works fine on older API levels.

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/ic_calendar"
    android:tint="@color/primary"
    />
Hector answered 19/3, 2015 at 21:53 Comment(7)
I am using ImageView - to display icon in it. Those icons are part of elements in my navigation drawer. And selected item in navigation drawer has different color, so I created each icon tinted and also selector for each icon. And I am using that selector for my icon. Selector: <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_activated="true" android:drawable="@drawable/ic_home_tinted" /> <item android:drawable="@drawable/ic_home" /> </selector>Corley
@Orochi Take a look at my answer as it come directly from Google's blogs. It mainly only works on Android 5.0+ but may work on some widgets for devices running pre-Android 5.0.Newly
@Orochi You are going to have to make custom views to "emulate" the same effect.Newly
@Orochi: Ah, sorry, misunderstood the context.Hector
So, should I just color the icon myself and put it in my drawable folder?Corley
You could use an image view, make the icon as white as possible, and make it any color you want with iv.setColorFilter(yourColor, Mode.Multiply); Make sure you import android.graphics.PorterDuff.ModeHannie
Same problem here. Sadly the tint with selector does not work with api < 21Threescore
N
17

A similar question has been asked before here: https://mcmap.net/q/246448/-tinting-checkbox-on-pre-v21

Android Drawable Tinting is supported in Android 5.0+ (API 21+) only. (It does say "At the moment this is limited to coloring the action bar and some widgets.").

Theming

...

When you set these attributes, AppCompat automatically propagates their values to the framework attributes on API 21+. This automatically colors the status bar and Overview (Recents) task entry.

On older platforms, AppCompat emulates the color theming where possible. At the moment this is limited to coloring the action bar and some widgets.

And

Widget tinting

When running on devices with Android 5.0, all of the widgets are tinted using the color theme attributes we just talked about. There are two main features which allow this on Lollipop: drawable tinting, and referencing theme attributes (of the form ?attr/foo) in drawables.

AppCompat provides similar behaviour on earlier versions of Android for a subset of UI widgets:

Everything provided by AppCompat’s toolbar (action modes, etc) EditText Spinner CheckBox RadioButton Switch (use the new android.support.v7.widget.SwitchCompat) CheckedTextView You don’t need to do anything special to make these work, just use these controls in your layouts as usual and AppCompat will do the rest (with some caveats; see the FAQ below).

Sources:

http://android-developers.blogspot.com/2014/10/appcompat-v21-material-design-for-pre.html

https://chris.banes.me/2014/10/17/appcompat-v21/

Newly answered 19/3, 2015 at 21:48 Comment(3)
Why was this downvoted? This is from the official documentation.Newly
Answer is outdated. ImageView also now supports android:tint via AppCompat, as in @Jonik's answer.Poetess
@VickyChijwani Submit an edit. And you mean AppCompatImageView, not ImageView.Newly
G
13

Now AppCompatImageView,AppCompatButton will replace the ImageView,Button to support tint on devices with lower API. Check link for more details AppCompatImageView,AppCompatButton

Gwendolyn answered 20/1, 2016 at 12:12 Comment(0)
S
6

For tinting images you could use imageView.setColorFilter(int color). This works from API 8 and worked for tinting my black image to a color I wanted. This can replace setImageTintList() but just using android:tint should also work.

Seymore answered 29/1, 2017 at 18:49 Comment(0)
I
5

Use this NameSpace
xmlns:app="http://schemas.android.com/apk/res-auto"

and after you can replace every android:tint with app:tint. This fix the issue for me.

Illation answered 8/6, 2018 at 12:35 Comment(0)
U
4

I'm a little late but here's how to do it.

val textInput = EditText(context)

val drawable = ContextCompat.getDrawable(context, R.drawable.your_drawable)
drawable?.let {
    myDrawable -> DrawableCompat.setTint(myDrawable, ContextCompat.getColor(context, R.color.your_color))
    textInput.setCompoundDrawablesRelativeWithIntrinsicBounds(null, null, myDrawable, null)
}
Usia answered 18/1, 2019 at 14:50 Comment(0)
I
1

This will do as you want, and should work on all Android versions of the support library:

Kotlin:

    @JvmStatic
    fun getTintedDrawable(inputDrawable: Drawable, @ColorInt color: Int): Drawable {
        val wrapDrawable = DrawableCompat.wrap(inputDrawable.mutate())
        DrawableCompat.setTint(wrapDrawable, color)
        DrawableCompat.setTintMode(wrapDrawable, Mode.SRC_IN)
        return wrapDrawable
    }

Java:

    public static Drawable getTintedDrawable(Drawable inputDrawable, @ColorInt int color) {
        Drawable wrapDrawable = DrawableCompat.wrap(inputDrawable.mutate());
        DrawableCompat.setTint(wrapDrawable, color);
        DrawableCompat.setTintMode(wrapDrawable, PorterDuff.Mode.SRC_IN);
        return wrapDrawable;
    }
Instillation answered 7/8, 2019 at 12:0 Comment(2)
I like this answer. mutate() and wrap is required for SDK < 21. For SDK >=21, the functions will just return the inputDrawable so there is no cost to use these functions. Besides, after wrapped, actually setTint and setTintMode can be directly called from wrapDrawable without using DrawableCompat's static method.Atavism
@ChesterFung In case the SDK>=21, what should it look like (please check before answering) ?Instillation
S
1

If anyone want create new drawable (tin1,tint2..) try this

<?xml version="1.0" encoding="utf-8"?>
<bitmap
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:src="@drawable/your_image"
  android:tint="@color/tint_color">
   </bitmap>
Samos answered 19/9, 2019 at 8:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.