安卓:底部导航视图-更改所选项目的图标

105

我已经在我的应用程序中添加了BottomNavigationView,如下所示。

main.xml

<android.support.design.widget.BottomNavigationView
        android:id="@+id/bottom_navigation"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        app:itemBackground="@color/colorPrimary"
        app:itemIconTint="@color/white"
        app:itemTextColor="@color/white"
        app:menu="@menu/bottom_navigation_main" />

bottom_navigation_main.xml

<?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/action_favorites"
        android:enabled="true"
        android:icon="@drawable/ic_favorite_white_24dp"
        android:title="@string/text_favorites"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_schedules"
        android:enabled="true"
        android:icon="@drawable/ic_access_time_white_24dp"
        android:title="@string/text_schedules"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_music"
        android:enabled="true"
        android:icon="@drawable/ic_audiotrack_white_24dp"
        android:title="@string/text_music"
        app:showAsAction="ifRoom" />
</menu>

MainActivity 点击

bottomNavigationView.setOnNavigationItemSelectedListener(
        new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.action_favorites:
                        //need change icon of favotites here.
                    case R.id.action_schedules:

                    case R.id.action_music:

                }
                return true;
            }
        });

我想要更改底部导航选中位置的图标。当用户点击其中一项时,我们如何实现此功能?

(如果用户点击了某个项目,则图标会更改为另一个图标)


1
任何在其菜单中使用选择器并想显示选择器颜色而不是默认底部导航栏颜色的人,请参考此答案 https://dev59.com/OVcP5IYBdhLWcg3wXI3Z#44516194。 - Amr
12个回答

182

您可以在drawable文件夹中创建可绘制选择器,根据视图中使用的小部件的状态更改图像。

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/calender_green" android:state_checked="true"/>
    <item android:drawable="@drawable/calender_black" android:state_checked="false"/>
</selector>

28
这种方法比编程方法更好。要指定的状态实际上是 android:state_checked 而不是 android:state_selected - Yuntao
1
你可以在这里使用以下代码:<android.support.design.widget.NavigationView . . app:itemTextColor="@drawable/your_selector"/> - sfmirtalebi
2
在KitKat Android版本中无法正常工作,应用程序崩溃了。 - Hitesh Sarsava
1
@ASN 从底部导航的XML代码中移除色调,以恢复图标的原始颜色。 - Abhinav Upadhyay
9
@AbhinavUpadhyay 尽管从 xml 中删除 itemIconTint 不起作用,但 bottomNavigationView.setItemIconTintList(null) 是解决方案。您知道在 xml 中的等效方法吗? - VipiN Negi
显示剩余6条评论

120

我发现使用选择器Drawable是更好的方法:

首先,在drawable文件夹中创建一个XML文件。例如,XML文件名为child_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/child" android:state_checked="false"/>
    <item android:drawable="@drawable/child_fill" android:state_checked="true"/>
</selector>

只需在底部导航栏布局文件 bottom_navigation_main.xml 的菜单项中添加child_selector:

例如:android:icon="@drawable/child_selector"

示例:

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

<item
    android:id="@+id/navigation_child"
    android:icon="@drawable/child_selector"
    android:title="@string/title_child" />

</menu>

必须在您的活动中添加以下行-

bottomNavigationView.setItemIconTintList(null);

2
由于已经有5个人提出了相同的解决方案,但在Java/Kotlin中仍然需要一行缺失的代码才能使其正常工作。不幸的是。 - milosmns
16
BottomNavigationView.setItemIconTintList(null); 的意思是将底部导航栏的图标颜色设置为默认颜色,即不经过任何着色处理。 - milosmns
能否只使用一个图标和色调来实现相同的效果,而不是使用两个图标(每个选中状态一个)? - user2966445
bottomNavigationView.setItemIconTintList(null); 你救了我一命。 - 徐誌良

102
如果以上方法无法帮助您更改所选项目图标,请将以下行添加到您的代码中:
bottomNavigationView.setItemIconTintList(null);

这将禁用所选项目图标的色彩效果。

我有同样的问题。我添加了选择器可绘制对象,以便在选中/已选择底部导航视图项目时更改其图标。


1
工作正常,谢谢。 - Shanmugapriyan M
2
谢谢你的答复,帮助我展示原始图标而不是彩色矩形。 - Chirag Jain
3
这是解决以上所有问题的答案,当您设置背景选择器时没有它就永远不会起作用,谢谢。 - Odaym
1
它运行良好。不要忘记使用可绘制的选择器创建菜单文件并在其中使用它。 - Djek-Grif
它起作用了,但我很好奇如何找到XML布局属性的等价项。 "@null" 对我没有用。 - VipiN Negi
谢谢,一个 UI 部门的电话就解决了! - Jumpa

47

您需要重置 onclick 图标,然后在 switch case 中,您需要仅设置需要更改的图标,因此仅当选定图标时才更改。

Menu menu = bottomNavigationView.getMenu();
menu.findItem(R.id.action_favorites).setIcon(favDrawable);

switch (item.getItemId()) {
                case R.id.action_favorites:
                     item.setIcon(favDrawableSelected);
                case R.id.action_schedules:
                case R.id.action_music:
            }

1
我认为明确添加声明“item”的代码片段会很有帮助。 MenuItem item = menu.findItem(R.id.action_favorites); - Akah
1
我会尝试这段代码,它可以工作,但是当我点击其他图标时,它不能设置默认图标,就像填充图标或未填充的图标。 - Ali
这个可以工作,但是当点击另一个项目时如何将图标重置回原始状态? - Eswar
1
在我的情况下,我只是尝试为不同的按钮更改不同的色调颜色,通过以下方式获得: bottomNavigationView.itemIconTintList = ColorStateList.valueOf(ContextCompat.getColor(this, iconColor)) - iamsujan
1
这个可以工作,但可能需要更多的工作。请检查下面的答案以获取更简洁的解决方案。 - Michael
这个方法实际上是可行的,唯一的问题是如果你想在选中时更改图标并在未选中时更改回来,因为通过 switch 传递的项只是被点击的那个,你将无法引用其他项,所以如果你取消选择它,你将无法恢复状态。请查看 Saiful Islam Sajib 下面的答案,了解如何实现选择器 drawable 的全部步骤,我认为这是最好和最干净的方法。 - Manuel Mariano Silva

35

好的,我想了解如何让每个项目都有自己的图像,并且在评论中有些混乱是关于它应该放在哪里的,因此我想撰写这篇答案。

首先创建您的菜单及其项目。您的选择器将在这些项目中的 ICON 值内部。这里我们有2个选择器,每个选择器都为其菜单项制作。

item
    android:id="@+id/navigation_home"
    android:icon="@drawable/navigation_home_selector"
    android:title="@string/title_home" />
item
    android:id="@+id/navigation_profile"
    android:icon="@drawable/navigation_profile_selector"
    android:title="@string/title_profile" />

现在这是你的选择器文件,它将被存储在drawable文件夹中。

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/menu_selected" android:state_checked="true"/>
    <item android:drawable="@drawable/menu" android:state_checked="false"/>
</selector>

最后一步由@KishanSolanki124提供。

将以下代码行添加到您的BottomNavigationView中。

BottomNavigationView.setItemIconTintList(null);

这就是它的全部。所有工作都像魔法一样顺利进行。


1
如何更改图标文本颜色? - Ashik Azeez
我相信你可以在navigationListener上设置它。BottomNavigationView.SetTextColor - A. Petrizza
这个答案(以及其他一些答案)中缺失的关键信息是选择器xml必须放置在名为navigation_home_selector.xml的drawable文件夹中的文件中;该名称使得从android:icon=@drawable/navigation_home_selector到智能可绘制对象的链接起作用。 - JohnT
@JohnT,这是由ICON部分内的实际值所暗示的。它告诉你该文件在drawable中以该名称存在。 - A. Petrizza

14

来自ajay singh的上述答案https://dev59.com/clkS5IYBdhLWcg3wJDUP#57248961帮助了我,同时也采用了上面的回答。

在res->drawable文件夹中以下代码(selector_stock_bottom_nav_view.xml)

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/button_and_tab_color" android:state_checked="true" />
    <item android:color="@android:color/darker_gray" android:state_checked="false" />
</selector>

这些是我底部导航视图中的属性

<com.google.android.material.bottomnavigation.BottomNavigationView

        app:itemIconTint="@drawable/selector_stock_bottom_nav_view" //To change icon color
        app:itemTextColor="@drawable/selector_stock_bottom_nav_view" //To change text color
        app:itemTextAppearanceActive="@style/stockBottomNavigationView.Active" //To change size of text during active state
        app:itemTextAppearanceInactive="@style/stockBottomNavigationView.InActive"
        app:menu="@menu/bottom_navigation_menu"
        app:labelVisibilityMode="labeled"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:layout_gravity="bottom"
        app:selectedBackgroundVisible="false"
        android:id="@+id/stock_bottom_navigation"/>

我在我的代码中没有使用“BottomNavigationView.setItemIconTintList(null)”。

现在,这里是最重要的代码,请确保在底部导航视图的监听器中返回“TRUE”,即:

private BottomNavigationView.OnNavigationItemSelectedListener stockBottomNavListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {

            return true;

        }
    };

额外奖励:改变文字大小的活动/非活动状态。请将以下代码放置在styles.xml文件中。

    <style name="stockBottomNavigationView.InActive" parent="@style/TextAppearance.AppCompat.Caption">
        <item name="android:textSize">7sp</item>
    </style>

    <style name="stockBottomNavigationView.Active" parent="@style/TextAppearance.AppCompat.Caption">
        <item name="android:textSize">8sp</item>
    </style>

上面的答案是从stackoverflow中与底部导航视图、图标和文本颜色/大小更改相关的各种答案中汇编而来的。


1
干得好,给我点个赞。这进一步增加了原问题的亮点。 - A. Petrizza

2
感谢 selector 方法,这对我很有效(api v26)。
对于那些想知道如何以编程方式将其设置回原始未选中图标的人,请在您的 OnNavigationItemSelectedListener 中加入以下内容,然后再执行您的 switch(Java)when(Kotlin)
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
    navigation.menu.getItem(0).setIcon(R.drawable.ic_tab_home)
    navigation.menu.getItem(1).setIcon(R.drawable.ic_tab_account)
    navigation.menu.getItem(2).setIcon(R.drawable.ic_tab_trading)
    navigation.menu.getItem(3).setIcon(R.drawable.ic_tab_wallet)
    when (item.itemId) {
        R.id.navigation_home -> {
            message.setText(R.string.title_home)
            item.setIcon(R.drawable.ic_tab_home_active)
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_account -> {
            message.setText(R.string.title_account)
            item.setIcon(R.drawable.ic_tab_account_active)
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_trading -> {
            message.setText(R.string.title_trading)
            item.setIcon(R.drawable.ic_tab_trading_active)
            return@OnNavigationItemSelectedListener true
        }
        R.id.navigation_wallet-> {
            message.setText(R.string.title_wallet)
            item.setIcon(R.drawable.ic_tab_wallet_active)
            return@OnNavigationItemSelectedListener true
        }
    }
    false
}

2
您可以使用此方法动态设置图标。 R.id.navigation_menu 是您在 R.menu.menu_bottom_navigation 中的项目 ID。
val menuItem = bottomNavigationView.menu.findItem(R.id.navigation_menu)
menuItem.setIcon(R.drawable.ic_icon)

1
找到答案了。我们可以使用


item.setIcon(R.drawable.icon_name) 

更改图标...将尝试改进答案。
 bottomNavigationView.setOnNavigationItemSelectedListener(
            new BottomNavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.action_favorites:
                            //change the icon
                         item.setIcon(R.drawable.icon_name);
                        case R.id.action_schedules:

                        case R.id.action_music:

                    }
                    return true;
                }
            });

2
这个可以工作,但是当点击另一个项目时,如何将图标重置回原始状态? - Eswar
1
@Eswar,请看一下我上面的答案。使用选择器,它可以完全使用两个不同的图像或颜色更改的图像(这就是我的应用程序正在做的)。 - A. Petrizza

0
默认情况下,Android将主要颜色设置为导航栏中的选定项目颜色。如果您将期望的选择颜色(例如蓝色)设置为...
<item name="colorPrimary">@color/blue</item>

选择的颜色将会是蓝色,无需进行其他操作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接