如何动态隐藏BottomNavigationView中的菜单项?

43
我希望根据某些条件动态隐藏BottomNavigationView的菜单项。 我尝试了以下方法,但它不起作用。
mBottomNavigationView.getMenu()
            .findItem(R.id.item_name)
            .setVisible(false);

mBottomNavigationView.invalidate();

你的代码应该按预期工作。你也可以尝试postInvalidate()。 - Fatih Santalu
也尝试了 postInvalidate,但它不起作用。如我在下面回答的那样,我使用了 removeItem 方法来实现相同的效果。 - Ram
@santalu 你是认真的吗?它会抛出“IndexOutOfBoundsException”异常。 - wonsuc
尝试使用以下代码:navView.getMenu().findItem(R.id.navigation_close).setVisible(true); navView.getMenu().findItem(R.id.navigation_back).setVisible(false); - Mahtab
9个回答

88
mBottomNavigationView.getMenu().removeItem(R.id.item_name);

removeItem可以解决问题。不确定为什么setVisible方法无效。


1
很高兴你找到了解决方案。我删除了我的回答,因为它没有帮助,投票支持了你的回答。可能是setVisibility不是BottomNavigationView或其继承方法的一种方法,而它确实使用菜单资源文件,因此可以使用菜单的公共方法,包括removeItem吗?https://developer.android.com/reference/android/support/design/widget/BottomNavigationView.html - Lew Perren
有没有办法动态设置它可见? - Jinson Paul
1
@JinsonPaul 我认为add()方法会起作用,因为removeItem可以用于删除。 但如果有人能解释为什么setVisible()方法不起作用,那就太好了。 - Ram
2
这对我来说是有效的,但如果我的菜单项少于5个,则底部导航项的间距不均匀。我认为这可能与“shift mode”有关?在完美的世界中,导航将平均分配任何数量的菜单项... - Dan
1
嗨,@Dan,我也遇到了同样的问题,当我删除一个项目时,它不会均匀分配其余的项目。 - Jono
如果有人在考虑为什么不用 'setVisibility(View.GONE)',而使用这个解决方案,这里是原因: 'setVisibility()'只是隐藏了视图,一旦您点击另一个菜单项,隐藏的菜单项就会再次显示,并且您可能需要做更多的工作。此外,菜单项不会等距分布在宽度上。 但是如果您将其删除,则不会出现这两个问题,因此似乎是最佳解决方案。 - Mayank Sehgal

18
您可以通过在Kotlin中使用建议的 isVisible 属性,并将其设置为 false 来隐藏菜单项。但是根据我的观察,在 Android 9 上,这会使您的菜单项从 BottomNavigationView 中删除。
bottomNavigation.menu.findItem(R.id.menu_item).isVisible = false

如果您在底部导航视图的背景上使用单一颜色,则可以使用类似的方法将菜单项保存在原位。例如右侧的一个。

// 0x000000 is black as an example
bottomNavigation.menu.findItem(R.id.menu_item).icon = ColorDrawable(0x000000)
// and disable for the actions
bottomNavigation.menu.findItem(R.id.menu_item).isEnabled = false

13

试一下这个:

navView.getMenu().findItem(R.id.your_menu_item_id).setVisible(true);
navView.getMenu().findItem(R.id.your_menu_item_id).setVisible(false);

9

我尝试了很多解决方案,但这个对我有用:

动态隐藏一个项目: bottomNavigationView.findViewById(R.id.xyz).setVisibility(View.GONE);

使项目可见: bottomNavigationView.findViewById(R.id.xyz).setVisibility(View.VISIBLE);


对我来说,.setVisibility() 函数出现了未解决的引用问题。 - Dan
1
这对我非常有效 - 我需要根据用户条件显示和隐藏一个项目,这比删除和添加更容易。 - 19Craig

7

setVisibility应该对你有用。以下示例是使用kotlin编写的。

bottomNavigationView.menu.findItem(R.id.navigation_item_two).isVisible = false

1
你的方法对我没有起作用,但是在Kotlin中 navigation.findViewById<View>(R.id.postEvent).visibility=View.GONE 起了作用。 - Mohammed Farhan

4

当隐藏某个菜单项时,removeItem会导致菜单栏中的菜单项位置发生变化。我找到了一种稍微更好的方法。创建一个菜单项组,将您想要隐藏的菜单xml放入其中。

在您的bottom_menu.xml文件中:

<menu...>
    <group android:id="@+id/hiddenmenu">
        <item.../>
        <item.../>
    </group>
    <item.../>
</menu>

在您的activity.cs文件中

Menu menu = mbottomNavigation.getMenu();  
menu.setGroupEnabled(R.id.hiddenmenu, false);

虽然在这种设置下,当所有菜单项都可见时,菜单项的选中状态会出现问题。也尝试过在空组中以编程方式添加菜单项,但该组停止响应了 GroupDisable...


3

在Kotlin中,您可以使用以下代码:

 mainActivitbinding.bottomNav.menu.removeItem(R.id.watch_list_tab)

还有一种方法可以添加一个项目吗?例如menu.addItem()? - Andrew

1

在 Kotlin 中,我是这样做的:

bottomNavigationView.rootView.findViewById<View>(R.id.nav_nearestRestaurant).visibility = View.GONE

但问题在于,如果您点击另一个项目,隐藏的项目会再次出现,因为底部栏在显示活动项目时重新加载其外观(因此,如果在XML菜单中可见,则再次可见(我认为是这样发生的))。

0
在我的情况下,我想要在授权片段中隐藏工具栏文本和BottomNavigationView项目的图标/标题,该片段处理应用程序的初始加载。当它确定用户已通过身份验证并从数据库获取其个人资料时,我会加载Feed片段,该片段从数据库获取数据并将其显示给用户。我所做的是向创建布局元素的活动添加以下方法,并从其片段调用它,传递一个布尔值以确定项目的可见性。
public void setBottomNavigationViewItemsVisibility(boolean value) {
    if (this.bottomNavigationView != null) {
        this.bottomNavigationView.setVisibility(View.VISIBLE);
        Menu menu = this.bottomNavigationView.getMenu();
        if (value) {
            int[] icons = {R.drawable.ic_event_white_24dp, R.drawable.ic_explore,
                    R.drawable.ic_store_white_24dp, R.drawable.ic_notifications_white_24dp};
            int[] titles = {R.string.feed, R.string.explore, R.string.finder, R.string.notifications};
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setIcon(icons[i]);
                menu.getItem(i).setTitle(titles[i]);
                menu.getItem(i).setEnabled(true);
            }
        } else {
            for (int i = 0; i < menu.size(); i++) {
                menu.getItem(i).setIcon(R.drawable.ic_empty);
                menu.getItem(i).setTitle(R.string.title_empty);
                menu.getItem(i).setEnabled(false);
            }
        }
    }
}

我们声明了一个可绘制ID数组和一个标题ID数组,以匹配我们在菜单XML文件中声明的内容。如果为真,则迭代菜单项并将它们的图标、标题和状态设置为默认值。如果为假,则将图标设置为透明图标(移除图标会影响其大小),将工具栏标题设置为空字符串并禁用它。
BottomNavigationView 菜单:
<?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"
    android:id="@+id/bottom_navigation_view_home">

    <item
        android:id="@+id/action_feed"
        android:enabled="true"
        android:icon="@drawable/ic_event_white_24dp"
        android:title="@string/feed"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_explore"
        android:enabled="true"
        android:icon="@drawable/ic_explore"
        android:title="@string/explore"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_finder"
        android:enabled="true"
        android:icon="@drawable/ic_store_white_24dp"
        android:title="@string/finder"
        app:showAsAction="ifRoom" />
    <item
        android:id="@+id/action_notifications"
        android:enabled="true"
        android:icon="@drawable/ic_notifications_white_24dp"
        android:title="@string/notifications"
        app:showAsAction="ifRoom" />
</menu>

空图标 (ic_empty.xml):

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <path
        android:fillColor="#00FFFFFF"
        android:pathData="M8" />
</vector>

空标题(title_empty):

<string name="title_empty" />

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