Ответ 1
Это снимет галочки с пунктов:
int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
mNavigationView.getMenu().getItem(i).setCheckable(false);
}
Я знаю, что можно выделить элемент навигации, вызвав setCheckedItem()
или вернуть истинное значение в onNavigationItemSelected
чтобы отобразить элемент в качестве выбранного элемента, но как я могу снять флажки с отмеченными элементами навигационного представления?
Это снимет галочки с пунктов:
int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
mNavigationView.getMenu().getItem(i).setCheckable(false);
}
Я увидел решение @arsent и дал ему попробовать, и он действительно сделает то, что вы хотите, чтобы отменить выбор всех элементов... но у меня возникла проблема в следующем сценарии:
NavigationView#setCheckedItem
)NavigationView#setCheckedItem
раз выберите пункт меню 1 (с помощью NavigationView#setCheckedItem
)В этом случае элемент 1 не будет отмечен как отмеченный. Это потому, что изнутри навигационное представление отслеживает ранее выбранный элемент, установленный на шаге 1, который не изменяется на шаге 2, и он просто пропускает шаг 3, потому что ранее выбранный элемент совпадает с тем, который мы сейчас выбираем.
Мое предложение (и альтернативное решение), чтобы избежать этого, просто имеет фиктивный невидимый элемент и использует NavigationView#setCheckedItem
для выбора этого элемента, когда вы хотите отменить выбор всех, например
<item
android:id="@+id/menu_none"
android:title=""
android:visible="false"/>
Отменить выбор всего, что нужно сделать
mNavigationView.setCheckedItem(R.id.menu_none);
Чтобы снять SubMenu
элементов MenuItems
включая элементы SubMenu
, вы должны использовать рекурсию -
private void unCheckAllMenuItems(@NonNull final Menu menu) {
int size = menu.size();
for (int i = 0; i < size; i++) {
final MenuItem item = menu.getItem(i);
if(item.hasSubMenu()) {
// Un check sub menu items
unCheckAllMenuItems(item.getSubMenu());
} else {
item.setChecked(false);
}
}
}
Вызовите метод выше, чтобы снять отметку со всех элементов, например ниже -
unCheckAllMenuItems(navigationView.getMenu());
просто сделайте свои вещи незаметными, например, так
<item
android:id="@+id/profile_item"
android:checkable="false"
android:title="@string/profile"/>
Цитируя @Codeversed, нет необходимости в создании элементов меню с добавленными накладными расходами! ". Но нет необходимости создавать несколько групп (в этом случае он создает @+id/grp1
и @+id/grp2
), чтобы снять @+id/grp2
с предыдущего отмеченного элемента.
Вы можете просто добавить одну группу для всех элементов с android:checkableBehavior
, например:
<group android:checkableBehavior="single">
<item
android:id="@+id/id1"
android:checked="true"
android:icon="@drawable/drawable1"
android:title="@string/string1" />
<item
android:id="@+id/id2"
android:icon="@drawable/drawable2"
android:title="@string/string2" />
</group>
Решения Joao не работали для меня как полностью ожидаемые. Это приведет к простому пробелу из непроверенного элемента "Вид" в моей навигации.
Просто не забудьте установить вид как ушедший:
<item
android:id="@+id/your_menu_item_id_to_hide"
android:title=""
android:visible="false"/>
bottomNavigationView.getMenu().findItem(R.id.your_menu_item_id_to_hide).setChecked(true);
bottomNavigationView.findViewById(R.id.your_menu_item_id_to_hide).setVisibility(View.GONE);
Решение Arsent в этом случае не требуется.
Я думаю, кто-то вроде меня использует эти методы, как это
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.nav_today:
break;
case R.id.nav_calendar:
navigationView.getMenu().performIdentifierAction(R.id.nav_today, 0);
navigationView.getMenu().getItem(0).setChecked(true);//or
navigationView.setCheckedItem(R.id.nav_today);//or
drawerLayout.closeDrawers();
break;
}
return true;
}
Попытка проверить R.id.nav_today
после того, как вы нажали на R.id.nav_calendar
, (checkableBehavior="single"
: checkableBehavior="single"
), к сожалению, это не сработает.
Это связано с тем, что после navigationView.setCheckedItem(R.id.nav_today)
кода navigationView.setCheckedItem(R.id.nav_today)
тогда R.id.nav_today
будет проверена немедленно, но после этого ваш клик по R.id.nav_calendar
проверяет себя.
Вот почему любые методы, которые вы используете, никогда не работают вообще. Это работа, но нужно немедленно переопределить ее.
Все, что вам нужно сделать, это окружить ваши группы следующим образом:
<group>
<group
android:id="@+id/grp1">
<item
android:id="@+id/nav_profile"
android:icon="@drawable/ic_account_circle_24dp"
android:title="@string/profile" />
</group>
<group
android:id="@+id/grp2">
<item
android:id="@+id/nav_settings"
android:icon="@drawable/ic_settings_24dp"
android:title="@string/settings" />
<item
android:id="@+id/nav_help"
android:icon="@drawable/topic_help"
android:title="@string/help_feedback" />
</group>
</group>
Не нужно зацикливать элементы меню с дополнительными накладными расходами!
Я совмещаю ответы @arsent и @Rahul и пишу этот код:
private void NavigationView_NavigationItemSelected(object sender, NavigationView.NavigationItemSelectedEventArgs e)
{
var size = navigationView.Menu.Size();
for (int i = 0; i < size; i++)
{
var item= navigationView.Menu.GetItem(i).SetChecked(false);
if (item.HasSubMenu)
{
for (int j = 0; j < item.SubMenu.Size(); j++)
{
item.SubMenu.GetItem(j).SetChecked(false);
}
}
}
e.MenuItem.SetChecked(true);
drawerLayout.CloseDrawers();
}
выше код для xamarin С# и работает, но вы можете легко преобразовать в java
Чтобы снять флажок внутри NavigationItemSelectedListener
мне пришлось использовать сообщение (в ветке пользовательского интерфейса):
App.getHandler().post(() -> menuItem.setChecked(false));
Полный пример:
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(
menuItem -> {
menuItem.setChecked(true);
mDrawerLayout.closeDrawers();
switch (menuItem.getItemId()) {
...
}
App.getHandler().post(() -> menuItem.setChecked(false));
return true;
});
ps в моем случае App.getHandler()
возвращает экземпляр Handler
для UI Thread Lopper
Мне пришлось использовать комбинацию всех решений, упомянутых здесь. В моем случае я хочу открыть URL Intent при щелчке элемента (откройте браузер). Выбранный элемент должен быть снят с проверки после нажатия и сброшен до элемента ранее. Важно понимать, что вы не можете снять отметку с элемента во время события прослушивания щелчка, так как проверенное состояние будет обработано впоследствии. Вот мое решение в Котлине:
val item = navigationView.menu.findItem(R.id.menu_item)
item.setOnMenuItemClickListener {
val oldItem = navigationView.checkedItem
rootView.postDelayed({ // you can use here any View to post a Runnable with a delay
navigationView.setCheckedItem(oldItem?.itemId ?: R.id.default_item)
}, 500)
browseURL("https://www.example.com")
true
}
Я использую Навигационный ящик в сочетании с Jetpack Navigation.