如何在新材质主题中更改后退箭头的颜色?

Posted

技术标签:

【中文标题】如何在新材质主题中更改后退箭头的颜色?【英文标题】:How to change color of the back arrow in the new material theme? 【发布时间】:2015-01-03 11:46:14 【问题描述】:

我已将我的 SDK 更新到 API 21,现在备份/后退图标是一个指向左侧的黑色箭头。

我希望它是灰色的。我该怎么做?

例如,在 Play 商店中,箭头是白色的。

我这样做是为了设置一些样式。我已将@drawable/abc_ic_ab_back_mtrl_am_alpha 用于homeAsUpIndicator。该drawable是透明的(只有alpha),但箭头显示为黑色。我想知道我是否可以像在DrawerArrowStyle 中那样设置颜色。或者,如果唯一的解决方案是创建我的@drawable/grey_arrow 并将其用于homeAsUpIndicator

<!-- Base application theme -->
<style name="AppTheme" parent="Theme.AppCompat.Light">

    <item name="android:actionBarStyle" tools:ignore="NewApi">@style/MyActionBar</item>
    <item name="actionBarStyle">@style/MyActionBar</item>

    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>

    <item name="homeAsUpIndicator">@drawable/abc_ic_ab_back_mtrl_am_alpha</item>
    <item name="android:homeAsUpIndicator" tools:ignore="NewApi">@drawable/abc_ic_ab_back_mtrl_am_alpha</item>
</style>

<!-- ActionBar style -->
<style name="MyActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid">

    <item name="android:background">@color/actionbar_background</item>
    <!-- Support library compatibility -->
    <item name="background">@color/actionbar_background</item>
</style>

<!-- Style for the navigation drawer icon -->
<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
    <item name="spinBars">true</item>
    <item name="color">@color/actionbar_text</item>
</style>

到目前为止,我的解决方案是使用看起来是白色的@drawable/abc_ic_ab_back_mtrl_am_alpha,并使用照片编辑器将其绘制成我想要的颜色。它可以工作,虽然我更喜欢使用 @color/actionbar_text,就像在 DrawerArrowStyle 中一样。

【问题讨论】:

到目前为止,基于 XML 的答案都没有为我解决此问题,但我已成功使用您的 homeAsUpIndicator / @drawable/abc_ic_ab_back_mtrl_am_alpha 代码将后退箭头设为白色。我更喜欢这个而不是侵入 Java。 旧但仍然。您使用的是 ActionBar 还是新的 Toolbar? 默认的应该有点灰色,通过在 Toolbar XML 标签中使用 android:theme="@style/Widget.AppCompat.Light.ActionBar"。它的颜色是#737373 检查我的答案 - 它超级简单,没有副作用。 【参考方案1】:

您可以通过代码来实现。获取返回箭头drawable,通过滤镜修改颜色,设置为返回按钮。

final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.grey), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);

修订版 1:

从 API 23 (Marshmallow) 开始,可绘制资源 abc_ic_ab_back_mtrl_am_alpha 更改为 abc_ic_ab_back_material

编辑:

你可以使用这段代码来达到你想要的结果:

toolbar.getNavigationIcon().setColorFilter(getResources().getColor(R.color.blue_gray_15), PorterDuff.Mode.SRC_ATOP);

【讨论】:

这是唯一对我有用的东西,而无需使用 colorControlNormal 更改所有其他小部件的色调 这个解决方案的问题是它会绘制所有其他后退箭头,如果您只想更改一个并将其余的保留为白色 它有效。请注意您应该使用ContextCompat.getDrawable(this, R.drawable.abc_ic_ab_back_mtrl_am_alpha),因为getResources.getDrawable(int) 已被弃用 另一种可能的解决方案是您自己获取该资源并将其放在您的可绘制文件夹中:) 注意23.2.0支持库中的abc_ic_ab_back_mtrl_am_alpha改为abc_ic_ab_back_material【参考方案2】:

查看ToolbarTintManager 源,drawable/abc_ic_ab_back_mtrl_am_alpha 被样式属性colorControlNormal 的值着色。

我确实尝试在我的项目中设置它(在我的主题中使用&lt;item name="colorControlNormal"&gt;@color/my_awesome_color&lt;/item&gt;),但它对我来说仍然是黑色的。

更新

找到了。您需要将actionBarTheme 属性(not actionBarStyle)设置为colorControlNormal

例如:

<style name="MyTheme" parent="Theme.AppCompat.Light">        
    <item name="actionBarTheme">@style/MyApp.ActionBarTheme</item>
    <item name="actionBarStyle">@style/MyApp.ActionBar</item>
    <!-- color for widget theming, eg EditText. Doesn't effect ActionBar. -->
    <item name="colorControlNormal">@color/my_awesome_color</item>
    <!-- The animated arrow style -->
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>

<style name="MyApp.ActionBarTheme" parent="@style/ThemeOverlay.AppCompat.ActionBar">       
    <!-- THIS is where you can color the arrow! -->
    <item name="colorControlNormal">@color/my_awesome_color</item>
</style>

<style name="MyApp.ActionBarStyle" parent="@style/Widget.AppCompat.Light.ActionBar">
    <item name="elevation">0dp</item>      
    <!-- style for actionBar title -->  
    <item name="titleTextStyle">@style/ActionBarTitleText</item>
    <!-- style for actionBar subtitle -->  
    <item name="subtitleTextStyle">@style/ActionBarSubtitleText</item>

    <!-- 
    the actionBarTheme doesn't use the colorControlNormal attribute
    <item name="colorControlNormal">@color/my_awesome_color</item>
     -->
</style>

【讨论】:

这应该是公认的答案。这次真是万分感谢。问题,当 SearchView 展开时,我找不到为显示的箭头着色的样式。有什么线索吗?它显然不受此答案的影响。 我还需要添加 ... 与 android: 前缀 不幸的是,这是一个 21 级 API,如果你想支持低于它的任何东西,它将无法工作。 如果您的父主题源自“NoActionBar”主题之一,那么在根主题而不是 actionBarTheme 中设置 colorControlNormal 是可行的方法。 我只用了 2 个小时的搜索、失败和再次搜索,最终得到了这个。有时 android 中的风格“系统”让我抓狂!当您有一个活动不使用与其他活动相同的样式时,使用此方法尤其重要。【参考方案3】:

尝试了以上所有建议。我设法更改工具栏中导航图标默认后退按钮箭头颜色的唯一方法是像这样在基本主题中设置 colorControlNormal。可能是因为父母正在使用 Theme.AppCompat.Light.NoActionBar

<style name="BaseTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="colorControlNormal">@color/white</item> 
  //the rest of your codes...
</style>

【讨论】:

最简单的答案,而不是摆弄其他代码,只需将此行添加到您的style.xml 记住 colorControlNormal 需要 API 21 @AdnanAli 如果您使用的是 AppCompat,它也适用于 ,因为 colorControlNormal android: 为前缀。 但这也改变了所有其他小部件的色调.. 有什么方法不影响其他小部件,例如复选框和单选按钮? 但这也会改变其他控件的颜色,比如单选按钮和文本编辑下的行。【参考方案4】:

需要为您的工具栏主题添加一个属性 -

<style name="toolbar_theme" parent="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
    <item name="colorControlNormal">@color/arrow_color</item>
</style>

将此工具栏主题应用到您的工具栏。

您可以直接应用到您的主题 -

<style name="CustomTheme" parent="Theme.AppCompat.Light.NoActionBar">
  <item name="colorControlNormal">@color/arrow_color</item> 
  //your code ....
</style>

【讨论】:

尝试接受的答案(可能是网上找到的最流行的解决方案)对我不起作用,但 这个有效 :) 太疯狂了使用 Android 编程时。 最简单的答案。这无需更改其他控件主题即可工作。您只需将自定义工具栏主题设置为工具栏即可。 :) 哦,您必须经历痛苦才能更改仅 1 个图标的颜色。第一个对我有用。第二个适用于自定义工具栏(显然还有其他东西)。 3 年后,非常感谢 Neo。【参考方案5】:

只需添加

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

到您当前的应用主题。

【讨论】:

这也改变了 android.support.v7.widget.AppCompatCheckBox 颜色【参考方案6】:

如果使用Toolbar,你可以试试这个

Drawable drawable = toolbar.getNavigationIcon();
drawable.setColorFilter(ContextCompat.getColor(appCompatActivity, colorId), PorterDuff.Mode.SRC_ATOP);

【讨论】:

这应该是公认的答案,恕我直言 - 它只针对箭头,使用最简单的方式设置箭头,并且在 API 21 下也兼容 如果您寻求更多自定义解决方案(在我的情况下标题和菜单图标的颜色不同),那么这就是您想要的解决方案 请注意,您可能需要在尝试调用 getNavigationIcon() 之前调用它:getSupportActionBar().setDisplayHomeAsUpEnabled(true); 最佳答案!谢谢。【参考方案7】:

正如之前大多数cmet所说,解决方案是添加

&lt;item name="colorControlNormal"&gt;@color/white&lt;/item&gt; 到您的应用主题。 但请确认您没有在布局的 Toolbar 元素中定义其他主题。

     <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            android:background="?attr/colorPrimary"
            android:elevation="4dp"
            android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

【讨论】:

Brilliant...我尝试了所有关于将其添加到主题中的答案,但没有成功...正如您所提到的,我有 android:theme="@style/ThemeOverlay.AppCompat。我的工具栏中的 ActionBar" 属性。一旦我删除它,它就开始工作了。【参考方案8】:

Carles 的答案是正确的答案,但在我撰写此答案时,getDrawable()、getColor() 等方法很少被弃用。所以更新后的答案是

Drawable upArrow = ContextCompat.getDrawable(context, R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(ContextCompat.getColor(context, R.color.white), PorterDuff.Mode.SRC_ATOP);
getSupportActionBar().setHomeAsUpIndicator(upArrow);

根据其他一些 *** 查询,我发现调用 ContextCompat.getDrawable() 类似于

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) 
    return resources.getDrawable(id, context.getTheme());
 else 
    return resources.getDrawable(id);


ContextCompat.getColor()

类似
public static final int getColor(Context context, int id) 
    final int version = Build.VERSION.SDK_INT;
    if (version >= 23) 
        return ContextCompatApi23.getColor(context, id);
     else 
        return context.getResources().getColor(id);
    

Link 1: ContextCompat.getDrawable()

Link 2: ContextCompat.getColor()

【讨论】:

应该是abc_ic_ab_back_material,而不是abc_ic_ab_back_mtrl_am_alpha【参考方案9】:

我找到了一种适用于 Lollipop 之前的解决方案。在“actionBarWidgetTheme”中设置“colorControlNormal”以更改 homeAsUpIndicator 颜色。从上面修改rockgecko的答案如下:

<style name="MyTheme" parent="Theme.AppCompat.Light">        
    <item name="actionBarTheme">@style/MyApp.ActionBarTheme</item>
    <item name="actionBarStyle">@style/MyApp.ActionBar</item>
    <!-- color for widget theming, eg EditText. Doesn't effect ActionBar. -->
    <item name="colorControlNormal">@color/my_awesome_color</item>
    <!-- The animated arrow style -->
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
    <!-- The style for the widgets on the ActionBar. -->
    <item name="actionBarWidgetTheme">@style/WidgetStyle</item>
</style>

<style name="WidgetStyle" parent="style/ThemeOverlay.AppCompat.Light">
    <item name="colorControlNormal">@color/my_awesome_color</item>
</style>

【讨论】:

【参考方案10】:

在 compileSdkVersoin 25 上,您可以这样做:

styles.xml

<style name="AppTheme" parent="Theme.AppCompat.Light">
     <item name="android:textColorSecondary">@color/your_color</item>
</style>

【讨论】:

【参考方案11】:

更改菜单导航图标颜色

在 style.xml 中:

<style name="MyMaterialTheme.Base" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="windowNoTitle">true</item>
    <item name="windowActionBar">false</item>
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
    <item name="android:textColor">@color/colorAccent</item>


</style>

<style name="DrawerArrowStyle" parent="@style/Widget.AppCompat.DrawerArrowToggle">
    <item name="spinBars">true</item>
    <item name="color">@color/colorPrimaryDark</item>
</style>







In Mainfests.xml :

<activity android:name=".MainActivity"
        android:theme="@style/MyMaterialTheme.Base"></activity>

【讨论】:

【参考方案12】:

使用以下方法:

private Drawable getColoredArrow() 
    Drawable arrowDrawable = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
    Drawable wrapped = DrawableCompat.wrap(arrowDrawable);

    if (arrowDrawable != null && wrapped != null) 
        // This should avoid tinting all the arrows
        arrowDrawable.mutate();
        DrawableCompat.setTint(wrapped, Color.GRAY);
    

    return wrapped;

现在你可以设置drawable了:

getSupportActionBar().setHomeAsUpIndicator(getColoredArrow());

【讨论】:

【参考方案13】:

解决方法很简单

只需将以下行放入您的样式中,命名为 AppTheme

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

现在您的整个 xml 代码将如下所示(默认样式)。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

        <item name="colorPrimary">#0F0F0F</item>
        <item name="android:statusBarColor">#EEEEF0</item>
        <item name="android:windowLightStatusBar">true</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowActivityTransitions">true</item>

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

【讨论】:

【参考方案14】:

另一个可能对您有用的解决方案是不要将您的工具栏声明为应用程序的操作栏(setActionBarsetSupportActionBar)并使用本页另一个答案中提到的代码在 onActivityCreated 中设置后退图标

final Drawable upArrow = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
upArrow.setColorFilter(getResources().getColor(R.color.grey), PorterDuff.Mode.SRC_ATOP);
toolbar.setNavigationIcon(upArrow);

现在,当您按下返回按钮时,您将不会收到 onOptionItemSelected 回调。但是,您可以使用setNavigationOnClickListener 进行注册。这就是我所做的:

toolbar.setNavigationOnClickListener(new View.OnClickListener() 
    @Override
    public void onClick(View view) 
        getActivity().onBackPressed(); //or whatever you used to do on your onOptionItemSelected's android.R.id.home callback
    
);

如果您使用菜单项,我不确定它是否会起作用。

【讨论】:

【参考方案15】:

这是我在 Material Components 中的做法:

<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
    <item name="drawerArrowStyle">@style/AppTheme.DrawerArrowToggle</item>
</style>

<style name="AppTheme.DrawerArrowToggle" parent="Widget.AppCompat.DrawerArrowToggle">
    <item name="color">@android:color/white</item>
</style>

【讨论】:

伙计,你拯救了我的一天。我一整天都花在这个上。我希望我能给你更多的选票。 对我不起作用,我不知道为什么?【参考方案16】:

我们遇到了同样的问题,我们只想设置

app:collapseIcon

最后在工具栏中的属性,我们没有找到,因为它没有很好的记录:)

<android.support.v7.widget.Toolbar
         android:id="@+id/toolbar"
         android:layout_
         android:layout_
         app:collapseIcon="@drawable/collapseBackIcon" />

【讨论】:

【参考方案17】:

试试这个

public void enableActionBarHomeButton(AppCompatActivity appCompatActivity, int colorId)

    final Drawable upArrow = ContextCompat.getDrawable(appCompatActivity, R.drawable.abc_ic_ab_back_material);
    upArrow.setColorFilter(ContextCompat.getColor(appCompatActivity, colorId), PorterDuff.Mode.SRC_ATOP);

    android.support.v7.app.ActionBar mActionBar = appCompatActivity.getSupportActionBar();
    mActionBar.setHomeAsUpIndicator(upArrow);
    mActionBar.setHomeButtonEnabled(true);
    mActionBar.setDisplayHomeAsUpEnabled(true);

函数调用:

enableActionBarHomeButton(this, R.color.white);

【讨论】:

设置 @link #DISPLAY_HOME_AS_UP 显示选项将自动启用主页按钮。【参考方案18】:

我刚刚将工具栏主题更改为@style/ThemeOverlay.AppCompat.Light

箭头变成深灰色

            <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_
            android:layout_
            android:gravity="center"
            app:layout_collapseMode="pin"
            app:theme="@style/ThemeOverlay.AppCompat.Light">

【讨论】:

【参考方案19】:

这对我有用:

将以下属性添加到您的主题中。

更改 api 21 上方的工具栏/操作栏后退箭头

<item name="android:homeAsUpIndicator">@drawable/your_drawable_icon</item>

更改 api 21 下方的工具栏/操作栏后退箭头

<item name="homeAsUpIndicator">@drawable/your_drawable_icon</item>

改变动作模式后退箭头

<item name="actionModeCloseDrawable">@drawable/your_drawable_icon</item>

移除工具栏/操作栏阴影

<item name="android:elevation" tools:targetApi="lollipop">0dp</item>
<item name="elevation">0dp</item>
<!--backward compatibility-->
<item name="android:windowContentOverlay">@null</item>

更改操作栏溢出可绘制

<!--under theme-->
<item name="actionOverflowButtonStyle">@style/MenuOverflowStyle</item>

<style name="MenuOverflowStyle" parent="Widget.AppCompat.ActionButton.Overflow">
<item name="srcCompat">@drawable/ic_menu_overflow</item>

注意:使用 'srcCompat' 代替 'android:src' 因为矢量可绘制支持低于 21 的 api

【讨论】:

如何根据我们的主题颜色更改@drawable/your_drawable_icon 的颜色?【参考方案20】:

更改后退/上箭头颜色的最简单(也是最好)的方法。最好的部分是 没有副作用(与其他答案不同)!

使用父级 Widget.AppCompat.DrawerArrowToggle 创建样式,定义 color 和您想要的任何其他属性。 在应用程序主题的drawerArrowStyle 属性上设置样式。

创建样式:

<style name="DrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
    <!--        Set that the nav buttons will animate-->
    <item name="spinBars">true</item>
    <!--        Set the color of the up arrow / hamburger button-->
    <item name="color">@color/white</item>
</style>

在 App Theme 中设置样式:

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <!--  Change global up-arrow color with no side-effects    -->
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>

要更改ToolBar 文本颜色(和其他属性),请创建此style

<style name="ToolbarStyle" parent="Widget.AppCompat.Toolbar">
    <item name="android:textColor">@color/white</item>
    <item name="titleTextColor">@color/white</item>
    <item name="colorControlNormal">@color/white</item> <!-- colorControlNormal is Probably not necessary    -->
</style>

然后在 AppTheme 上设置该样式:

<!-- Base application theme. -->
<style name="AppTheme.MyProduceApp" parent="Theme.MaterialComponents.Light.NoActionBar.Bridge">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>

    <!--  Style the toolbar (mostly the color of the text) -->
    <item name="toolbarStyle">@style/ToolbarStyle</item>
    <!--  Change color of up-arrow    -->
    <item name="drawerArrowStyle">@style/DrawerArrowStyle</item>
</style>

【讨论】:

对我不起作用【参考方案21】:

您可以像这样以编程方式更改导航图标的颜色:

mToolbar.setNavigationIcon(getColoredArrow()); 

private Drawable getColoredArrow() 
        Drawable arrowDrawable = getResources().getDrawable(R.drawable.abc_ic_ab_back_mtrl_am_alpha);
        Drawable wrapped = DrawableCompat.wrap(arrowDrawable);

        if (arrowDrawable != null && wrapped != null) 
            // This should avoid tinting all the arrows
            arrowDrawable.mutate();
                DrawableCompat.setTintList(wrapped, ColorStateList.valueOf(this.getResources().getColor(R.color.your_color)));
            
        

        return wrapped;

【讨论】:

【参考方案22】:
private fun setToolbarNavigationIconColor(context: Context, toolbar: Toolbar?, color: Int) 
    val drawableBack = toolbar?.navigationIcon
    drawableBack?.let 
        val drawableWrap = DrawableCompat.wrap(drawableBack).mutate()
        DrawableCompat.setTint(
            drawableWrap, ContextCompat.getColor(context, white)
        )
        toolbar.navigationIcon = drawableWrap
    

【讨论】:

【参考方案23】:

我看到了所有解决方案,但没有解决问题,如果您需要解决问题,只需在 XMl 文件中添加此代码,如果您将其变暗,则使其变亮

 app:theme="@style/ThemeOverlay.AppCompat.Light"

【讨论】:

【参考方案24】:

只需从您的主题中删除 android:homeAsUpIndicatorhomeAsUpIndicator 即可。 DrawerArrowStyle 样式中的color 属性必须足够。

【讨论】:

我已经试过了,箭头是黑色的。请注意,此箭头与您打开抽屉时看到的箭头不同(该箭头受color 属性影响)。抽屉箭头有点大。 所以,看来您必须提供自己的可绘制资源。您可以使用此工具生成它:shreyasachar.github.io/AndroidAssetStudio【参考方案25】:

除非有更好的解决方案...

我所做的是拍摄@drawable/abc_ic_ab_back_mtrl_am_alpha 的图像,这些图像似乎是白色的,然后使用照片编辑器将它们绘制成我想要的颜色。

【讨论】:

以上是关于如何在新材质主题中更改后退箭头的颜色?的主要内容,如果未能解决你的问题,请参考以下文章

更改后退按钮 iOS 中箭头的颜色

角材料日期选择器箭头颜色

更改后退按钮上的颜色(在ActionBar上)

Actionbar中后退箭头的颜色不会更改

如何更改expandableListView的箭头颜色? [关闭]

仅在 swift 中更改后退栏按钮项的颜色