java – Change Toolbar overflow icon color-ThrowExceptions

Exception or error:

I have an android.support.v7.widget Toolbar in my Android app. The background color of this is bright orange and the best looking color on top of this would be white instead of black.

I have the default color on black and not white. Since it would conflict with other stuff, that is almost impossible to override. I cannot change the primary text color to white!

I’ve managed to change the title color.
What I’m looking for right now is how I can change the action button color as well (to white).

enter image description here

My code:

Main activity:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".UI.activities.MainActivity">

<android.support.v7.widget.Toolbar
    android:id="@+id/r2_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="?attr/colorPrimary"
    android:elevation="4dp"
    app:titleTextColor="@color/primary_text_material_light"
    app:subtitleTextColor="@color/primary_text_material_light"
    android:theme="@style/R2Theme.Toolbar"/>

<fragment android:name="com.r2retail.r2retailapp.UI.fragments.SetupFragment"
    android:layout_below="@+id/r2_toolbar"
    android:id="@+id/list"
    android:layout_weight="1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


</RelativeLayout>

Menu bar:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">

<item android:id="@+id/about"
    android:icon="@drawable/ic_menu"
    android:title="About"
    app:showAsAction="never"/>

</menu>

Styles:

<resources>

<style name="R2Theme" parent="Theme.AppCompat.Light.NoActionBar">=
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorPrimary</item>
    <item name="android:textColorPrimary">@color/secondary_text_material_dark</item>
    <item name="android:textColorSecondaryInverse">@color/primary_text_material_light</item>
</style>

<style name="R2Theme.Toolbar" parent="R2Theme">
    <item name="actionMenuTextColor">@color/primary_text_material_light</item>
</style>

</resources>
How to solve:

In styles:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    ...
    <item name="actionOverflowButtonStyle">@style/MyOverflowButtonStyle</item>
</style>

<style name="MyOverflowButtonStyle" parent="Widget.AppCompat.ActionButton.Overflow">
    <item name="android:tint">#62ff00</item>
</style>

Result:

enter image description here

###

The solution is to replace icon itself.

1st

Go to values/styles and in your styles.xml file add:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="android:actionOverflowButtonStyle">@style/MyActionButtonOverflow</item>
</style>

<style name="MyActionButtonOverflow" parent="android:style/Widget.Holo.Light.ActionButton.Overflow">
    <!--Here you need to put name of drawable you will create during the next step-->
    <item name="android:src">@drawable/your_white_icon</item> 
</style>

2nd

Then go to drawable folder. Right mouse click -> new -> vector asset.
Then press on Icon image and choose from suggested icon named ic_more_vert_black_24dp.

Customize it -> press next -> finish.

Then open newly created icon file. Code looks like this.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FFFFFFFF" <!-- Here u can change color-->
        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z"/>
</vector>

Change fillColor attribute to the color you need. Put this file to the styles how described in 1st step.

Voila! Color of our three dots changed not depending on base app styles (result for #FF2012 color).

enter image description here

###

An alternative way, in code instead of XML:

public static boolean colorizeToolbarOverflowButton(@NonNull Toolbar toolbar, @ColorInt int color) {
    final Drawable overflowIcon = toolbar.getOverflowIcon();
    if (overflowIcon == null)
        return false;
    toolbar.setOverflowIcon(getTintedDrawable(toolbar.getContext(), overflowIcon, toolbarIconsColor));
    return true;
}

public static Drawable getTintedDrawable(@NonNull Context context, @NonNull Drawable inputDrawable, @ColorInt int color) {
    Drawable wrapDrawable = DrawableCompat.wrap(inputDrawable);
    DrawableCompat.setTint(wrapDrawable, color);
    DrawableCompat.setTintMode(wrapDrawable, Mode.SRC_IN);
    return wrapDrawable;
}

The function will return true if succeeded to colorize the overflow icon.

And another alternative, in case you prefer not to use a tinted drawable:

public static boolean colorizeToolbarOverflowButton(@NonNull Toolbar toolbar, @ColorInt Integer color) {
    final Drawable overflowIcon = toolbar.getOverflowIcon();
    if (overflowIcon == null)
        return false;
    final PorterDuffColorFilter colorFilter = toolbarIconsColor == null ? null : new PorterDuffColorFilter(toolbarIconsColor, PorterDuff.Mode.MULTIPLY);
    overflowIcon.setColorFilter(colorFilter);
    return true;
}

In addition, if you wish to colorize the icons of the action items and the nav item, you can try this (based on here):

/**
 * Use this method to colorize toolbar icons to the desired target color
 *
 * @param toolbarView       toolbar view being colored
 * @param toolbarIconsColor the target color of toolbar icons
 */
@JvmStatic
@UiThread
fun colorizeToolbarActionItemsAndNavButton(toolbarView: Toolbar, @ColorInt toolbarIconsColor: Int?) {
    //https://snow.dog/blog/how-to-dynamicaly-change-android-toolbar-icons-color/
    val colorFilter = if (toolbarIconsColor == null) null else PorterDuffColorFilter(toolbarIconsColor, Mode.MULTIPLY)
    for (i in 0 until toolbarView.childCount) {
        val v = toolbarView.getChildAt(i)
        //Step 1 : Changing the color of back button (or open drawer button).
        if (v is ImageButton) {
            //Action Bar back button
            v.drawable.mutate().colorFilter = colorFilter
        }
        if (v is ActionMenuView) {
            for (j in 0 until v.childCount) {
                //Step 2: Changing the color of any ActionMenuViews - icons that
                //are not back button, nor text, nor overflow menu icon.
                val innerView = v.getChildAt(j)
                if (innerView is ActionMenuItemView) {
                    val drawablesCount = innerView.compoundDrawables.size
                    for (k in 0 until drawablesCount) {
                        if (innerView.compoundDrawables[k] != null) {
                            innerView.post { innerView.compoundDrawables[k].mutate().colorFilter = colorFilter }
                        }
                    }
                }
            }
        }
    }
}

Usage:

override fun onCreateOptionsMenu(menu: Menu): Boolean {
    menuInflater.inflate(R.menu.menu_main, menu)
    toolbar.doOnPreDraw {
        colorizeToolbarActionItemsAndNavButton(toolbar,0xffff0000.toInt())
    }
    return true
}

###

For AndroidX users (really don’t know if it works using old Support Library):

TL;DR:

<style name="MyToolbarTheme">
  <item name="colorControlNormal">@color/white</item>
</style>

Apply MyToolbarTheme to your Toolbar view.


Long explanation:

Widget.AppCompat.ActionButton.Overflow extends Base.Widget.AppCompat.ActionButton.Overflow. We’ll be talking about the latter:

On the default implementation:

<style name="Base.Widget.AppCompat.ActionButton.Overflow" parent="RtlUnderlay.Widget.AppCompat.ActionButton.Overflow">
  <item name="srcCompat">@drawable/abc_ic_menu_overflow_material</item>
  ...
</style>

On API 21 implementation:

<style name="Base.Widget.AppCompat.ActionButton.Overflow" parent="android:Widget.Material.ActionButton.Overflow">
  <item name="android:src">@null</item>
  <item name="srcCompat">@drawable/abc_ic_menu_overflow_material</item>
</style>

On API 23 and higher implementation:

It extends android:Widget.Material.ActionButton.Overflow.

<style name="Widget.Material.ActionButton.Overflow">
  <item name="src">@drawable/ic_menu_moreoverflow_material</item>
  ...
</style>

We can notice that every implementation uses @drawable/ic_menu_moreoverflow_material.

Inside this drawable’s implementation you can see the following:

android:tint="?attr/colorControlNormal"

Leave a Reply

Your email address will not be published. Required fields are marked *