【发布时间】:2016-03-17 03:15:33
【问题描述】:
我知道可以通过调用setCheckedItem() 或在onNavigationItemSelected 中返回真值来突出显示导航视图项以将该项显示为选定项,但是如何取消选中导航视图的选中项?
【问题讨论】:
标签: android navigationview android-navigationview
我知道可以通过调用setCheckedItem() 或在onNavigationItemSelected 中返回真值来突出显示导航视图项以将该项显示为选定项,但是如何取消选中导航视图的选中项?
【问题讨论】:
标签: android navigationview android-navigationview
这将取消选中项目:
int size = mNavigationView.getMenu().size();
for (int i = 0; i < size; i++) {
mNavigationView.getMenu().getItem(i).setCheckable(false);
}
【讨论】:
setChecked(false); 而不是true
setCheckable(false)替换setChecked(false)解决了这个问题
setCheckable(false) 结合 setChecked(false) 用于我的案例中的每个项目。
我看到了@arsent 解决方案并试了一下,它确实会做你想做的事,即取消选择所有项目......但是,我在以下场景中遇到了问题:
NavigationView#setCheckedItem)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" 才能工作,但是一旦我这样做了,那就太完美了!
要取消选中所有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>
【讨论】:
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解决方案。
【讨论】:
您需要做的就是像这样围绕您的小组:
<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_calendar后尝试检查R.id.nav_today,(顺便说一句:checkableBehavior="single"),不幸的是它不起作用。
那是因为在您的代码navigationView.setCheckedItem(R.id.nav_today) 被调用之后,R.id.nav_today 将被立即检查,但在此之后,您对R.id.nav_calendar 的点击会自动检查。
这就是为什么您使用的任何方法似乎都不起作用的原因。这是工作,但立即被覆盖。
【讨论】:
要在 NavigationItemSelectedListener 中取消选中它,我必须使用 post(到 UI 线程):
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;
});
附言在我的情况下,App.getHandler() 返回 UI Thread Lopper 的 Handler 实例
【讨论】:
我必须结合使用此处提到的所有解决方案。就我而言,我想在单击项目时打开一个 URL 意图(打开浏览器)。单击的项目应在单击后取消选中并重置为之前的项目。重要的是要了解,您不能在单击侦听器事件期间取消选中项目,因为已选中的状态将在之后处理。所以这是我在 Kotlin 中的解决方案:
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
}
我将Navigation Drawer 与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);
}
【讨论】: