Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tint a Button's drawable using appcompat 23.3.0?

Tags:

I am facing several issues with the new AppCompat 23.3.x and drawables. First of all, I had to go back and remove:

vectorDrawables.useSupportLibrary = true

Because the AppCompat reverted that so now, my app is generating PNG again. Ok, however, I was tinting a button (the drawableTop) in a way that stopped working completely (for devices previous to M).

Here is the method I was using:

private void toggleState(boolean checked) {
    Drawable[] drawables = getCompoundDrawables();
    Drawable wrapDrawable = DrawableCompat.wrap(drawables[1]);
    if (checked) {
        DrawableCompat.setTint(wrapDrawable.mutate(), ContextCompat.getColor(getContext(),
                R.color.colorPrimary));
        setTextColor(ContextCompat.getColor(getContext(), R.color.colorPrimary));
    } else {
        DrawableCompat.setTint(wrapDrawable.mutate(), ContextCompat.getColor(getContext(),
                R.color.icon_light_enabled));
        setTextColor(ContextCompat.getColor(getContext(), R.color.text_primary_light));
    }
}

The thing is, I have a custom Button class that is checkable, if checked, drawableTop and text have a different color that if it's not checked.

Doing this was working (with appcompat 23.2.0), but now, it is not (below Android M). Believe me or not, but doing this, when it hits setTint the icon is not visible anymore at all.

To make it work, I have to do like follows:

 DrawableCompat.setTint(wrapDrawable.mutate(), ContextCompat.getColor(getContext(),R.color.colorPrimary));
 setCompoundDrawablesWithIntrinsicBounds(null, wrapDrawable, null, null);

So everytime I tint them, I have to call setCompoundDrawablesWithIntrinsicBounds again. Doing so makes everything to work again. However, I am a bit concerned about the performance of setting the drawable everytime. Basically, I wonder if there is a better way or something I am missing.

I know a Button has setCompoundDrawableTintList which would be marvelous but its minimum API is level 23.

like image 351
Ferran Negre Avatar asked Apr 22 '16 17:04

Ferran Negre


1 Answers

Not enough reputation to make a comment but I just ran into this issue as well. Really sucks and good thing I caught it today instead of after release.

/**
 * Tinting drawables on Kitkat with DrawableCompat
 * requires wrapping the drawable with {@link DrawableCompat#wrap(Drawable)} prior to tinting it
 * @param view The view containing the drawable to tint
 * @param tintColor The color to tint it.
 */
public static void tintViewBackground(View view, int tintColor) {
    Drawable wrapDrawable = DrawableCompat.wrap(view.getBackground());
    DrawableCompat.setTint(wrapDrawable, tintColor);
    view.setBackground(wrapDrawable);
}

/**
 * Tinting drawables on Kitkat with DrawableCompat
 * requires wrapping the drawable with {@link DrawableCompat#wrap(Drawable)} prior to tinting it
 * @param drawable The drawable to tint
 * @param tintColor The color to tint it.
 */
public static void tintDrawable(Drawable drawable, int tintColor) {
    Drawable wrapDrawable = DrawableCompat.wrap(drawable);
    DrawableCompat.setTint(wrapDrawable, tintColor);
}

Even odder is this ONLY happens on Lollipop, normal behavior is seen on Kitkat and API 23+.

like image 94
Brandon McAnsh Avatar answered Sep 28 '22 01:09

Brandon McAnsh