android - 为什么可检查的菜单项不显示复选框

标签 android android-menu drawerlayout android-navigationview

NavigationView 菜单:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
   <group android:checkableBehavior="all">
        <item
            android:id="@+id/itemFoo1"
            android:checkable="true"
            android:title="Foo1" />
        <item
            android:id="@+id/itemFoo2"
            android:checkable="true"
            android:title="Foo2" />
    </group>
</menu>

Android Studio 中的设计器显示复选框: enter image description here

但是,应用程序不显示复选框:

enter image description here

有人可以提供这方面的线索吗?

使用菜单的布局:

<com.google.android.material.navigation.NavigationView
    android:id="@+id/navigationView"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_gravity="end"
    app:menu="@menu/activity_foo_view"/>

最佳答案

NavigationView 的默认行为是一次选择一个项目;例如,这通常会选择抽屉布局中的 fragment 。

正如 Mike M 在评论中指出的那样;使某个项目可检查并不意味着它是一个 CheckBox

因此,您必须向菜单项添加一个 CheckBox,有两个选项可以实现此目的:

  • 选项 1:使用 CheckBox 作为 app:actionViewClass

  • 选项 2:通过 app:actionLayout 使用自定义布局:检查 this answer为此

使用CheckBox作为app:actionViewClass:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
   <group android:checkableBehavior="all">
        <item
            android:id="@+id/itemFoo1"
            android:checkable="true"
            app:actionViewClass="android.widget.CheckBox"
            android:title="Foo1" />
        <item
            android:id="@+id/itemFoo2"
            android:checkable="true"
            app:actionViewClass="android.widget.CheckBox"
            android:title="Foo2" />
    </group>
</menu>

点击复选框将切换其状态,但点击项目文本则不会;这可以通过获取 menuItem ActionView 并使用 setChecked() 切换 CheckBox 以编程方式修复:

private final NavigationView.OnNavigationItemSelectedListener navViewlistener = new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.itemFoo1 || id == R.id.itemFoo2) {
            CheckBox actionView = (CheckBox) item.getActionView();
            actionView.setChecked(!actionView.isChecked()); // Toggle the CheckBox
        }

        return true;
    }
};

navView.setNavigationItemSelectedListener(navViewlistener);

更新

I used app:actionViewClass="android.widget.CheckBox" for a while. The main issue is the the checkbox is independent of the item. Clicking it does not trigger NavigationItemSelectedListener. That is the main reason I am seeking a new way.

这是对的;我们可以通过编程方式修复此问题,方法是每当选中/取消选中持有的 CheckBox 时触发 MenuItem 点击事件。

但主要问题是,它可能导致无限循环;当我们在 onNavigationItemSelected 中选中/取消选中 CheckBox 时;这将触发另一个 MenuItem 点击等等。

因此,这里是一个 mIsCheckBoxClick bool 值,并且在调用 setChecked() 之前停止 CheckBox 监听器,然后重新附加它们;所有这些都是为了避免循环:

private boolean mIsCheckBoxClick;

@Override
protected void onCreate(Bundle savedInstanceState) {
    // ....... add your code

    // Enable CheckBox listeners at the NavView menu items by default 
    addFooListeners(navView, true);
}

private void addFooListeners(final NavigationView navView, boolean enabled) {
    adjustNavViewItemListener(navView.getMenu().findItem(R.id.itemFoo1), navView, enabled);
    adjustNavViewItemListener(navView.getMenu().findItem(R.id.itemFoo2), navView, enabled);
}

private void adjustNavViewItemListener(final MenuItem item, final NavigationView navView, boolean enabled) {
    final CheckBox fooChBox = (CheckBox) item.getActionView();
    CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            mIsCheckBoxClick = true;
            navView.getMenu().performIdentifierAction(item.getItemId(), 0); // perform a click on MenuItem to trigger OnNavigationItemSelectedListener
        }
    };
    fooChBox.setOnCheckedChangeListener(enabled ? listener : null);
}


private final NavigationView.OnNavigationItemSelectedListener navViewlistener = new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {

        int id = item.getItemId();

        if (id == R.id.itemFoo1 || id == R.id.itemFoo2) {
            
            // Loop prevention check
            if (!mIsCheckBoxClick) {
                CheckBox actionView = (CheckBox) item.getActionView();
            
                // Stop the CheckBox listeners
                addFooListeners(navView, false);
                
                actionView.setChecked(!actionView.isChecked());
                
                // Reattach the CheckBox listeners
                addFooListeners(navView, true);
            }
            mIsCheckBoxClick = false;           
        }

        return true;
    }
};

关于android - 为什么可检查的菜单项不显示复选框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69596736/

相关文章:

java - 如何解析从php返回的数组到android中的String数组

android - 获取Android中videoView的mediaPlayer

Android VKontake 官方客户端。如何获得授权

android - 如何仅在 Room 实体为空时更新它的列?

android - 膨胀类 android.support.v4.widget.drawerlayout 时出错

java - 在包 'showAsAction' 中找不到属性 'android' 的资源标识符

Android:自定义应用程序的菜单(例如背景颜色)

android - 单击打开上下文菜单

java - android.support.v4.widget.DrawerLayout 无法转换为 android.support.v4.widget.DrawerLayout$DrawerListener

android - 需要在 Android 的抽屉布局中使 ListView 垂直居中