androidtoolbarandroid-appcompattint

MenuItem tinting on AppCompat Toolbar


When I use drawables from the AppCompat library for my Toolbar menu items the tinting works as expected. Like this:

<item
    android:id="@+id/action_clear"
    android:icon="@drawable/abc_ic_clear_mtrl_alpha"  <-- from AppCompat
    android:title="@string/clear" />

But if I use my own drawables or actually even copy the drawables from the AppCompat library to my own project it will not tint at all.

<item
    android:id="@+id/action_clear"
    android:icon="@drawable/abc_ic_clear_mtrl_alpha_copy"  <-- copy from AppCompat
    android:title="@string/clear" />

Is there some special magic in the AppCompat Toolbar that only tint drawables from that library? Any way to get this to work with my own drawables?

Running this on API Level 19 device with compileSdkVersion = 21 and targetSdkVersion = 21, and also using everything from AppCompat

abc_ic_clear_mtrl_alpha_copy is an exact copy of the abc_ic_clear_mtrl_alpha png from AppCompat

Edit:

The tinting is based on the value I have set for android:textColorPrimary in my theme.

E.g. <item name="android:textColorPrimary">#00FF00</item> would give me a green tint color.

Screenshots

Tinting working as expected with drawable from AppCompat Tinting working as expected with drawable from AppCompat

Tinting not working with drawable copied from AppCompat Tinting not working with drawable copied from AppCompat


Solution

  • Because if you take a look at the source code of the TintManager in AppCompat, you will see:

    /**
     * Drawables which should be tinted with the value of {@code R.attr.colorControlNormal},
     * using the default mode.
     */
    private static final int[] TINT_COLOR_CONTROL_NORMAL = {
            R.drawable.abc_ic_ab_back_mtrl_am_alpha,
            R.drawable.abc_ic_go_search_api_mtrl_alpha,
            R.drawable.abc_ic_search_api_mtrl_alpha,
            R.drawable.abc_ic_commit_search_api_mtrl_alpha,
            R.drawable.abc_ic_clear_mtrl_alpha,
            R.drawable.abc_ic_menu_share_mtrl_alpha,
            R.drawable.abc_ic_menu_copy_mtrl_am_alpha,
            R.drawable.abc_ic_menu_cut_mtrl_alpha,
            R.drawable.abc_ic_menu_selectall_mtrl_alpha,
            R.drawable.abc_ic_menu_paste_mtrl_am_alpha,
            R.drawable.abc_ic_menu_moreoverflow_mtrl_alpha,
            R.drawable.abc_ic_voice_search_api_mtrl_alpha,
            R.drawable.abc_textfield_search_default_mtrl_alpha,
            R.drawable.abc_textfield_default_mtrl_alpha
    };
    
    /**
     * Drawables which should be tinted with the value of {@code R.attr.colorControlActivated},
     * using the default mode.
     */
    private static final int[] TINT_COLOR_CONTROL_ACTIVATED = {
            R.drawable.abc_textfield_activated_mtrl_alpha,
            R.drawable.abc_textfield_search_activated_mtrl_alpha,
            R.drawable.abc_cab_background_top_mtrl_alpha
    };
    
    /**
     * Drawables which should be tinted with the value of {@code android.R.attr.colorBackground},
     * using the {@link android.graphics.PorterDuff.Mode#MULTIPLY} mode.
     */
    private static final int[] TINT_COLOR_BACKGROUND_MULTIPLY = {
            R.drawable.abc_popup_background_mtrl_mult,
            R.drawable.abc_cab_background_internal_bg,
            R.drawable.abc_menu_hardkey_panel_mtrl_mult
    };
    
    /**
     * Drawables which should be tinted using a state list containing values of
     * {@code R.attr.colorControlNormal} and {@code R.attr.colorControlActivated}
     */
    private static final int[] TINT_COLOR_CONTROL_STATE_LIST = {
            R.drawable.abc_edit_text_material,
            R.drawable.abc_tab_indicator_material,
            R.drawable.abc_textfield_search_material,
            R.drawable.abc_spinner_mtrl_am_alpha,
            R.drawable.abc_btn_check_material,
            R.drawable.abc_btn_radio_material
    };
    
    /**
     * Drawables which contain other drawables which should be tinted. The child drawable IDs
     * should be defined in one of the arrays above.
     */
    private static final int[] CONTAINERS_WITH_TINT_CHILDREN = {
            R.drawable.abc_cab_background_top_material
    };
    

    Which pretty much means they have particular resourceIds whitelisted to be tinted.

    But I guess you can always see how they're tinting those images and do the same. It's as easy as set the ColorFilter on a drawable.