Я знаю, что можно выделить элемент представления навигации, вызвав setCheckedItem()
, или вернуть истинное значение в onNavigationItemSelected
, чтобы отобразить элемент как выбранный, но как снять отметку с отмеченных элементов в представлении навигации?
Как снять отметку с отмеченных пунктов в представлении навигации?
Ответы (12)
Это снимет отметку с пунктов:
int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
mNavigationView.getMenu().getItem(i).setChecked(false);
}
setChecked(false);
, а не true
- person arsent; 26.12.2017
setChecked(false)
на setCheckable(false)
- person Roberto; 28.12.2017
setCheckable(false)
в сочетании с setChecked(false)
для каждого элемента, сработавшего в моем случае.
- person kkaun; 01.09.2018
Я увидел решение @arsent и попробовал, и оно действительно сделает то, что вы хотите, а именно отменит выбор всех элементов ... но у меня возникла проблема в следующем сценарии:
- Выберите пункт меню 1 (используя
NavigationView#setCheckedItem
) - Отмените выбор всех элементов в соответствии с решением @arsent
- Снова выберите пункт меню 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);
checkable="true"
, чтобы он работал, но как только я это сделал, он стал идеальным!
- person AtkinsSJ; 09.08.2018
Чтобы снять отметку со всех 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
), чтобы снять отметку с предыдущего отмеченного элемента.
Вы можете просто добавить одну группу для всех элементов с помощью 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>
Решения Жоао не сработали для меня, как ожидалось. Это приведет к появлению пустого места в непроверенном представлении элементов в моей навигации.
Просто не забудьте установить вид как пропавший:
<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 в этом случае не нужен.
Все, что вам нужно сделать, это окружить свои группы вот так:
<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>
Нет необходимости зацикливать пункты меню с дополнительными накладными расходами!
Думаю, кто-то вроде меня использует эти методы вот так
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"
), к сожалению, не сработает.
Это потому, что после того, как ваш код navigationView.setCheckedItem(R.id.nav_today)
будет вызван, R.id.nav_today
будет немедленно проверен, но после этого ваш щелчок по R.id.nav_calendar
проверит себя.
Вот почему какие бы методы вы ни использовали, кажется, что они вообще никогда не работают. Это работа, но ее нужно немедленно отменить.
Чтобы снять отметку внутри 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;
});
p.s. в моем случае App.getHandler()
возвращает Handler
экземпляр для UI Thread Lopper
Мне пришлось использовать комбинацию всех упомянутых здесь решений. В моем случае я хочу открыть намерение URL-адреса при щелчке по элементу (открыть браузер). Выбранный элемент должен быть снят после щелчка и сброшен к элементу ранее. Важно понимать, что вы не можете снять отметку с элемента во время события прослушивателя кликов, так как отмеченное состояние будет обработано впоследствии. Итак, это мое решение в Котлине:
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.
Я комбинирую ответы @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 C # и работает, но вы можете легко преобразовать в java
@arsent ответ правильный, но setCheckable (false) снимает отметку со всех элементов, это предотвращает проверку элементов в будущем.
Просто используйте setChecked (false)
int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
mNavigationView.getMenu().getItem(i).setChecked(false);
}