【问题标题】:Navigation Drawer Group Title when Items populated Dynamically动态填充项目时的导航抽屉组标题
【发布时间】:2019-03-14 21:25:58
【问题描述】:

我在我的应用中使用标准导航抽屉来显示两种菜单项:

  1. 高级常规项目,如仪表板、详细视图等。

  2. 每个用户帐户的特定屏幕。

第二组项目需要动态填充,即我无法在 XML 中指定这些。我正在努力获得第二组的头衔。

这是我当前的 menu.xml 文件

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="General">
        <menu>
            <group
                android:id="@+id/main_group"
                android:orderInCategory="1">
                <item
                    android:id="@+id/nav_dashboard"
                    android:icon="@drawable/ic_dashboard"
                    android:title="@string/nav_dashboard"
                    android:checkable="true"
                    android:checked="true"/>
                <item
                    android:id="@+id/nav_all"
                    android:icon="@drawable/ic_list"
                    android:title="@string/nav_all"
                    android:checkable="true" />
            </group>

        </menu>
    </item>
    <item android:title="Accounts">
        <menu>
            <group
                android:id="@+id/accounts_group"
                android:orderInCategory="2">

            </group>
        </menu>
    </item>
</menu>

标题Accounts 在我的导航抽屉上不可见。但是,如果我不动态填充项目,而是在 XML 中放置一些随机项目,它是可见的。

这就是我填充菜单项的方式:

for (int index = 0; index < accountsList.size(); index++) {
    MainActivityPresenter.AccountInfo accountInfo = accountsList.get(index);
    menu.add(R.id.accounts_group, index + MENU_ITEM_ID, 1, accountInfo.name).setCheckable(true);
}

寻找提示。为什么我动态添加项目时项目标题Accounts 不显示?谢谢!

【问题讨论】:

    标签: android navigation-drawer


    【解决方案1】:

    首先您需要更改菜单 XML 布局,如下所示,这样标题将无法选择,只能检查子项。

    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="General"
        android:checkable="false"
        android:id="@+id/general_menu">
        <menu>
            <item
                android:id="@+id/nav_dashboard"
                android:icon="@drawable/ic_dashboard"
                android:title="@string/nav_dashboard"/>
            <item
                android:id="@+id/nav_all"
                android:icon="@drawable/ic_list"
                android:title="@string/nav_all"/>
        </menu>
    </item>
    <item android:title="Accounts"
        android:checkable="false"
        android:id="@+id/accounts_group">
        <menu>
            <!-- filled at runtime -->
        </menu>
    </item>
    </menu>
    

    然后在您的代码中,您需要访问正确的菜单item,这对我们来说就像一个“逻辑组”,您可以使用此代码来执行此操作:

    //use the index of the group, in your case Account item is the 2nd in the
    //XML this means its index is 1    
    val menuItem: MenuItem = navigationView.menu.getItem(1)
    //save the generated view Id, because if you need a reference after you need 
    //to save newSubMenuId property somewhere before adding the item
    val newSubMenuId = View.generateViewId()
    //add the item to the submenu. The order value it's used to position the
    //item inside the group. With 1 it will be the first item, 2 will be the second and so on
    val addedItem = menuItem.subMenu.add(Menu.NONE, newSubMenuId, 1, R.string.new_account)
    //add a nice icon to the inserted sub-item
    addedItem.setIcon(R.drawable.ic_menu_account_icon)
    

    现在您将遇到问题,如果您的菜单 XML 中没有 groups,您将无法使用 android:checkableBehavior="single" 属性来防止在您的 NavigationView 中多选项目。

    要解决最后一个问题,我们可以这样做:

    val navigationView: NavigationView = findViewById(R.id.nav_view)
    navigationView.setNavigationItemSelectedListener { selectedItem ->
    
        //loop trough all the main items (which are groups for us) to remove the checked state
        for (i in 0 until navigationView.menu.size()) {
            val menuItem = navigationView.menu.getItem(i)
            menuItem.isChecked = false
            if (menuItem.hasSubMenu()) {
                //if they have a subMenu, loop trough all the subitems
                //and remove the checked state from them too
                for (z in 0 until menuItem.subMenu.size()) {
                    val subMenuItem = menuItem.subMenu.getItem(z)
                    subMenuItem.isChecked = false
                }
            }
        }
        // set item as selected to persist highlight
        selectedItem.isChecked = true
        // close drawer when item is tapped
        drawerLayout.closeDrawers()
    
        // Add code here to update the UI based on the item selected
        // For example, swap UI fragments here
    
        true
    }
    

    所有的代码都是用Kotlin写的,但我想如果你还在用的话,把它转换成Java就不会那么麻烦了。顺便说一句,如果您有问题,请询问:)

    PS:创建时不需要指定.setCheckable(true) 新物品。默认情况下可以检查新项目

    【讨论】:

    • 谢谢。您指定的 XML 解决了我的问题。但是,有一些改进。 1)您不需要每次点击时都“取消选择”每个项目。只需记录上一个选中的项目并取消选中它即可。 2) setCheckable(true) 是必需的 - 没有它,textColor,背景 stateList 不起作用,即当 state=checked 时指定的背景可绘制在项目被选中时不显示。
    • 1) 是的,当然,你可以随心所欲地改进它:) 2) 这真的很奇怪......(但没关系)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多