Toolbar icon tinting on Android

Another option is to use the new support for vector drawables in the support library.

See res/xml/ic_search.xml in blog post AppCompat — Age of the vectors

Notice the reference to ?attr/colorControlNormal

<vector xmlns:android="..."
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0"
    android:tint="?attr/colorControlNormal">
    <path
        android:pathData="..."
        android:fillColor="@android:color/white"/>
</vector>

I actually was able to do this on API 10 (Gingerbread) and it worked very well.

Edit: It worked on API 22 also...

Here's the final result.

enter image description here

Note: The icon is a drawable resource in the drawable folder(s).

Now here's how its done:

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu);

    MenuItem item = menu.findItem(R.id.action_refresh);
    Drawable icon = getResources().getDrawable(R.drawable.ic_refresh_white_24dp);
    icon.setColorFilter(getResources().getColor(R.color.colorAccent), PorterDuff.Mode.SRC_IN);

    item.setIcon(icon);
}

At this point you can change it to any color you want!


Here is the solution that I use. Call tintAllIcons after onPrepareOptionsMenu or the equivalent location. The reason for mutate() is if you happen to use the icons in more than one location; without the mutate, they will all take on the same tint.

public class MenuTintUtils {
    public static void tintAllIcons(Menu menu, final int color) {
        for (int i = 0; i < menu.size(); ++i) {
            final MenuItem item = menu.getItem(i);
            tintMenuItemIcon(color, item);
            tintShareIconIfPresent(color, item);
        }
    }

    private static void tintMenuItemIcon(int color, MenuItem item) {
        final Drawable drawable = item.getIcon();
        if (drawable != null) {
            final Drawable wrapped = DrawableCompat.wrap(drawable);
            drawable.mutate();
            DrawableCompat.setTint(wrapped, color);
            item.setIcon(drawable);
        }
    }

    private static void tintShareIconIfPresent(int color, MenuItem item) {
        if (item.getActionView() != null) {
            final View actionView = item.getActionView();
            final View expandActivitiesButton = actionView.findViewById(R.id.expand_activities_button);
            if (expandActivitiesButton != null) {
                final ImageView image = (ImageView) expandActivitiesButton.findViewById(R.id.image);
                if (image != null) {
                    final Drawable drawable = image.getDrawable();
                    final Drawable wrapped = DrawableCompat.wrap(drawable);
                    drawable.mutate();
                    DrawableCompat.setTint(wrapped, color);
                    image.setImageDrawable(drawable);
                }
            }
        }
    }
}

This won't take care of the overflow, but for that, you can do this:

Layout:

<android.support.v7.widget.Toolbar
    ...
    android:theme="@style/myToolbarTheme" />

Styles:

<style name="myToolbarTheme">
        <item name="colorControlNormal">#FF0000</item>
</style>

This works as of appcompat v23.1.0.