Заголовок группы ящиков навигации при динамическом заполнении элементов - PullRequest
0 голосов
/ 15 марта 2019

Я использую стандартный Навигационный ящик в моем приложении для отображения двух видов пунктов меню:

  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 не отображается при динамическом добавлении элементов?Спасибо!

1 Ответ

1 голос
/ 15 марта 2019

Прежде всего вам необходимо изменить макет 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)

Теперь у вас возникнет проблема, без group s в вашем XML-меню, вы не сможете использовать свойство 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) при создании нового элемента.Новинки можно проверять по умолчанию

...