Jahir Fiquitiva
Jahir Fiquitiva

Reputation: 1509

How to properly tint VectorDrawables so they work in pre-lollipop devices?

Well, I recently started using VectorDrawables and I thought they would work normally in all android versions, but it seems they cause crashes in pre-lollipop devices.

The thing is I'm creating a tinted drawable with this code:

Drawable tintedDrawable = getTintedIcon(
                ContextCompat.getDrawable(context, R.drawable.ic_android),
                ThemeUtils.darkTheme ? light : dark);

public static Drawable getTintedIcon(Drawable drawable, int color) {
    if (drawable != null) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && drawable instanceof VectorDrawable) {
            drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN);
        }
        drawable = DrawableCompat.wrap(drawable.mutate());
        DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN);
        DrawableCompat.setTint(drawable, color);
        return drawable;
    } else {
        return null;
    }
}

After creating the tinted drawable I set it using: imageView.setImageDrawable(tintedDrawable);

This works as expected in Lollipop and newer Android versions, but it doesn't in older versions.

According to Chris Banes' Medium post, I can use either: app:srcCompat="@drawable/ic_android"

or imageView.setImageResource(R.drawable.ic_android);

But what can I do when I need to tint it programmatically? Can someone help and/or explain it to me?

Thanks in advance.

I already have this in my build.gradle file, just in case:

android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
    }  
 }

Upvotes: 0

Views: 970

Answers (2)

brettbrdls
brettbrdls

Reputation: 483

Try to declare this to ImageView:

app:srcCompat="@drawable/ic_iconname"/>

But before that, if you're using gradle v2.0 +, add this to your gradle:

vectorDrawables.useSupportLibrary = true

Source: AppCompat - Age of the vectors

Upvotes: 1

user3241683
user3241683

Reputation: 1

Don't if this will help but this is the code that I use and have not experienced any issues as of yet.

public static boolean isAboveOrEqualAPILvl(int apiLvl) {
    return Build.VERSION.SDK_INT >= apiLvl;
}

@TargetApi(Build.VERSION_CODES.M)
public static int getResourceColor(@NonNull Context context, @ColorRes int id) {
    if (isAboveOrEqualAPILvl(Build.VERSION_CODES.M)) {
        return context.getColor(id);
    } else {
        //noinspection deprecation
        return context.getResources().getColor(id);
    }
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Nullable
public static Drawable getIconDrawable(@NonNull Context context, @DrawableRes int drawableId,
                             int colorId, boolean isMutate) {
    Drawable drawable;
    if (isAboveOrEqualAPILvl(Build.VERSION_CODES.LOLLIPOP)) {
        drawable = context.getDrawable(drawableId);
    } else {
        //noinspection deprecation
        drawable = context.getResources().getDrawable(drawableId);
    }
    drawable = isMutate ? DrawableCompat.wrap(drawable).mutate() : DrawableCompat.wrap(drawable);
    if (colorId>-2) {
        DrawableCompat.setTint(drawable, getResourceColor(context, colorId));
    }
    return drawable;
}

public static void changeDrawableTint(@Nullable Context context, @NonNull Drawable drawable,
                               @ColorRes int colorId) {
    if (context==null) { return; }
    DrawableCompat.setTint(drawable, getResourceColor(context, colorId));
}

Upvotes: 0

Related Questions