Back Arrow and Overflow Icons Wrong Color in Pre-L

2019-01-16 17:00发布

问题:

On pre-Lollipop devices, the overflow menu icon and back button on actionbar changed to black color after upgrading to Support Library 23.2.0. They are white (which is the right color) before the upgrade.

The correct color is:

The wrong color appears for pre-Lollipop devices after the upgrade, as shown with the overflow menu icon:

The theme in sytle.xml (pre-v21/Lollipop):

<resources xmlns:android="http://schemas.android.com/apk/res/android" >
    <!--Used on the application level by the manifest.-->
    <style name="app_theme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/app_primary_colour</item>
        <item name="colorPrimaryDark">@color/app_primary_dark_colour</item>
        <item name="colorAccent">@color/app_accent_colour</item>
        <item name="android:windowBackground">@color/app_background</item>
        <item name="searchViewStyle">@style/custom_search_view_style</item>
    </style>

    <!--Used by activities.-->
    <style name="app_theme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <!--TODO: What are these?-->
    <style name="app_theme.app_bar_overlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
    <style name="app_theme.popup_overlay" parent="ThemeOverlay.AppCompat.Light" /> ... ... </resources>

I have looked here and here but didn't fix the issue.

UPDATE: Also see this Google bug report: https://code.google.com/p/android/issues/detail?id=201918

回答1:

I could fix.

I found that AppCompat theme is using following resource for overflow button: abc_ic_menu_overflow_material.xml

Content of this resource is:

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0"
        android:tint="?attr/colorControlNormal">
    ...
</vector>

Then, I connected the dots:

  • First: It is using colorControlNormal
  • Second: It is using vector

HOW TO FIX

According to Library V23.2.0 Release notes (LINK HERE), we have to update build.gradle to add support to Vector:

build.gradle

Add following lines to your build gradle

Gradle 2.0 (I did not tested):

android {  
    defaultConfig {  
        vectorDrawables.useSupportLibrary = true  
    }  
}  

Gradle 1.5 (I'm using this.. it works):

android {  
    defaultConfig {  
        generatedDensities = []  
    }  

    aaptOptions {  
        additionalParameters "--no-version-vectors"  
    }  
}  

Fixing your theme

This step may be ignored. Some base themes already set colorControlNormal to white (such as AppCompat.Dark.ActionBar).

However, in my case, all button colors remained black and I had to add the colorControlNormal to my theme and override it with white color.

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
    <item name="colorControlNormal">@color/white</item>
</styel>

I hope this can help you.

This was how I fixed my issue.



回答2:

Just update to the Support Library 23.2.1, which fixes the problem.

For AppCompat users, the flags for enabling support vector drawables described in the 23.2 blog post (http://goo.gl/073Mpo) are no longer required for usage of AppCompat.

https://plus.google.com/+AndroidDevelopers/posts/BZgzpAqkd8G



回答3:

I had this problem when changing the support library to 23.2.0. The back arrow and overflow icons turned black.

protected void changeBackArrow() {
    final Drawable upArrow = ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_material);
    upArrow.setColorFilter(ContextCompat.getColor(this, R.color.textColorPrimary), PorterDuff.Mode.SRC_ATOP);

    getSupportActionBar().setHomeAsUpIndicator(upArrow);
}

As of support 23.1 Toolbar now has getOverflowIcon() and setOverflowIcon() methods

protected void changeOverflowMenu() {
    final Drawable overflowIcon = getToolbar().getOverflowIcon();
    overflowIcon.setColorFilter(ContextCompat.getColor(this, R.color.colorWhite), PorterDuff.Mode.SRC_ATOP);

    getToolbar().setOverflowIcon(overflowIcon);
}


回答4:

I am writing this answer, because the accepted answer did not work for me (even though it is correct). But I solved it in another way, so I'm sharing it here:

First of all, I did not add anything to the gradle file. I am using Support Library v23.4.0, as it is the latest one at the time of writing this post.

What worked for me is to hardcode the tint color or path color, instead of using a color resource reference. For example, use android:fillColor="#fff" instead of android:fillColor="@android:color/white":

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:tint="#fff"
    android:viewportHeight="24"
    android:viewportWidth="24">
    <path
        android:fillColor="#fff"
        android:pathData="M9.5,3A6.5,6.5 0 0,1 16,9.5C16,11.11 15.41,12.59 14.44,13.73L14.71,14H15.5L20.5,19L19,20.5L14,15.5V14.71L13.73,14.44C12.59,15.41 11.11,16 9.5,16A6.5,6.5 0 0,1 3,9.5A6.5,6.5 0 0,1 9.5,3M9.5,5C7,5 5,7 5,9.5C5,12 7,14 9.5,14C12,14 14,12 14,9.5C14,7 12,5 9.5,5Z" />
</vector>

Observe the tint and path color in the above code snippet. Earlier I was assigning the color as "@color/someColor" but it was showing a warning that it will work only for v21 and above, and it was actually not working below v21. So I changed that to a hardcoded value. Again it's a simple workaround/hack and probably not a correct solution.



回答5:

I wrote a helper (i use a static Helper class with useful functions) function, which can be called at the start of the onCreate() of a activity:

    public static void setWhiteBackArrow(ActionBar actionbar, Context context){
    //needed due to bug in Android compile version 23
    // https://code.google.com/p/android/issues/detail?id=201918
    if (actionbar != null) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
            final Drawable upArrow = ContextCompat.getDrawable(context, android.support.v7.appcompat.R.drawable.abc_ic_ab_back_material);
            upArrow.setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.SRC_ATOP);
            //ActionBar aBar = context.getSupportActionBar();
            actionbar.setHomeAsUpIndicator(upArrow);
        }
    }    

Call it like this in the onCreate() of activity:

Helper.setWhiteBackArrow(getSupportActionBar(), this);