68

我的 Android 应用程序中有以下菜单布局:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/item1" 
          android:titleCondensed="Options"
          android:title="Highlight Options" 
          android:icon="@android:drawable/ic_menu_preferences" />

   <item android:id="@+id/item2" 
         android:titleCondensed="Persist"
         android:title="Persist" 
         android:icon="@android:drawable/ic_menu_preferences" 
         android:checkable="true" />
</menu>

我的问题是,当我在 Android 模拟器中运行我的应用程序时,第二个菜单项似乎不是“可检查的”。该项目应该有一个绿色的勾号,对吧?表明它是可检查的。

难道我做错了什么?

4

9 回答 9

83

布局看起来不错。但是您必须在代码中选中和取消选中菜单项。

文档中:

当一个可勾选项被选中时,系统会调用你各自的选中项回调方法(如onOptionsItemSelected())。您必须在此处设置复选框的状态,因为复选框或单选按钮不会自动更改其状态。您可以使用 查询项目的当前状态(就像用户选择它之前的状态),isChecked()然后使用 设置选中状态setChecked()

于 2011-06-04T20:33:19.973 回答
41

将 s包装item在一个group元素中,如下所示:

<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="all">
        <item android:id="@+id/item1"
              android:titleCondensed="Options"
              android:title="Highlight Options"
              android:icon="@android:drawable/ic_menu_preferences">
        </item>
        <item android:id="@+id/item2"
              android:titleCondensed="Persist"
              android:title="Persist"
              android:icon="@android:drawable/ic_menu_preferences"
              android:checkable="true">
        </item>
    </group>
</menu>

来自Android 文档

android:checkableBehavior 属性接受:

单个 - 只能检查组中的一项(单选按钮)

all - 可以选中所有项目(复选框)

none - 没有可检查的项目

于 2011-06-04T20:30:32.113 回答
26

actionViewClass您可以通过将 设置为可检查的小部件来创建可检查的菜单项,例如android.widget.CheckBox

res/menu/ menu_with_checkable_menu_item.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorite"
        android:checkable="true"
        android:title="@string/action_favorite"
        app:actionViewClass="android.widget.CheckBox"
        app:showAsAction="ifRoom|withText" />
</menu>

actionLayout如果您设置为带有样式的布局,您甚至可以将其设置为可检查的星形android.widget.CheckBox

资源/布局/action_layout_styled_checkbox.xml

<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
    style="?android:attr/starStyle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

res/menu/ menu_with_checkable_star_menu_item.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorites"
        android:checkable="true"
        android:title="@string/action_favorites"
        app:actionLayout="@layout/action_layout_styled_checkbox"
        app:showAsAction="ifRoom|withText" />
</menu>

设置值

menuItem.setChecked(true/false);

获取价值

menuItem.isChecked()

将 MenuItem 转换为 CheckBox

CheckBox checkBox= (CheckBox) menuItem.getActionView();
于 2016-03-22T17:07:51.967 回答
4

我发现最好的解决方案是仅使用我当前 API (27-28) 中的 onOptionsItemSelected() 方法。

@Override
   public boolean onOptionsItemSelected(MenuItem item) 
   {    

//Copy from here...
       int itemId = item.getItemId();

       if(item.isChecked())                          
       { 
           if(R.id.edit_tile_checkbox == itemId)     //Individual checkbox logic
           {   /*TODO unchecked Action*/} 
           item.setChecked(false);                   //Toggles checkbox state.
       }
       else
       {
            if(R.id.edit_tile_checkbox == itemId)    //Individual checkbox logic
            {/*TODO checked Action*/}
            item.setChecked(true);                   //Toggles checkbox state.
       }
//...To here in to your onOptionsItemSelected() method, then make sure your variables are all sweet.

       return super.onOptionsItemSelected(item);
   }

我在这里花了很长时间才得到这个答案。无论出于何种原因,上面的答案都没有帮助(我是一个回归的新手,我确定我可能搞砸了一些东西)。可能有更好的方法来做到这一点,因此欢迎有帮助的批评。

于 2020-06-06T10:33:59.073 回答
1

回答是因为这里的答案看起来很长而且很复杂。我这里有一些确切的 Kotlin 代码

在顶部覆盖您的活动并覆盖函数onMenuItemClick,具有处理按钮单击以打开菜单的函数。

有一个数组或列表,其中包含检查值并在重新创建菜单时设置检查

注意:此代码不会保持菜单打开,它只确保选中的项目保持选中状态。我注意到堆栈溢出有很多解决方案,所以如果这是你想要的,请查看它们

class exampleActivity : AppCompatActivity(), PopupMenu.OnMenuItemClickListener {
   private var checkChecked = arrayListOf(false,false)
   //some code

  fun clickBTN(v: View){
        val popup = PopupMenu(this,v)
        popup.setOnMenuItemClickListener(this)
        popup.inflate(R.menu.yourmenufilename)
        //assuming you have 2 or more menu items
        popup.menu[0].isChecked = checkChecked[0]
        popup.menu[1].isChecked = checkChecked[1]
        popup.show()
  }

  override fun onMenuItemClick(item: MenuItem?): Boolean {
     when(item?.itemID){
        R.id.item0 -> {
                item.isChecked = !item.isChecked
                checkChecked[0] = item.isChecked
                return true
        }
        R.id.item1 -> {
                item.isChecked = !item.isChecked
                checkChecked[1] = item.isChecked
                return true
        }
  }
}

当然在 XML 中你应该有你的按钮和菜单设置。示例菜单在这里

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/item0"
        android:title="@string/hi"
        android:checkable="true"/>
    <item android:id="@+id/item1"
        android:title="@string/yo"
        android:checkable="true"/>
</menu>
于 2019-10-07T23:40:42.350 回答
0

这可能取决于主题,但我的菜单没有显示复选框。我发现了这个

注意:图标菜单中的菜单项不能显示复选框或单选按钮。如果您选择将图标菜单中的项目设为可勾选,那么您必须在每次状态在开和关之间切换时通过交换图标和/或文本来亲自指示状态。

于 2014-06-05T17:29:07.870 回答
0

对于以编程方式添加菜单项,

@Override
public boolean onCreateOptionsMenu(Menu menu) {

    menu.add("Item1").setActionView(R.layout.action_layout_checkbox).setCheckable(true);
    return super.onCreateOptionsMenu(menu);
}

资源/布局/action_layout_checkbox.xml

<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
于 2018-03-09T09:04:37.130 回答
0

我在菜单中有两个项目,并设置为可在menu.xml文件中检查,如下所示

    <item
        android:id="@+id/A"
        android:title="A"
        app:showAsAction="never"
        android:checkable="true"/>
    <item
        android:id="@+id/B"
        android:title="B"
        app:showAsAction="never"
        android:checkable="true"/> 

菜单复选框的逻辑如下。

@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {

    switch (item.getItemId()) {
        case R.id.A:
           //logic goes here


            if(item.isChecked())
            {
             //logic is it is checked
             item.setChecked(false);
            }
            else
            {
               //logic is it is not checked
                item.setChecked(true);
            }
            return true;
        case R.id.B:
         //logic for second checkbox goes here


            if(item.isChecked())
            {
             //logic is it is checked
                item.setChecked(false);
            }
            else
            {
             //logic is it is not checked
                item.setChecked(true);
            }
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
于 2020-07-23T08:07:02.090 回答
0

读这个

如前所述,“人工检查”只是冰山一角。它以如此快的速度将菜单闪开,用户看不到任何事情发生,而且非常反直觉,令人沮丧,并且实际上完全是废话。(REAL TASK因此)允许用户头脑消化复选框事件。

好消息:这是可以做到的,它确实有效,这就是你的做法。@TouchBoarder 做得最好,所以我会复制他的代码。然后开发它。

the idea is to detect if the checkbox is clicked, then (and only if that one is picked) slightly suppress the menu removal, add a timer for 500ms then close the menu, this give the "tick" animation of the checkbox time to run并创造正确的“感觉”

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <item
        android:id="@+id/action_favorite"
        android:checkable="true"
        android:title="@string/action_favorite"
        app:actionViewClass="android.widget.CheckBox"
        app:showAsAction="ifRoom|withText" />
</menu>

然后你像往常一样做这个方法,但你确保你添加了所有这些额外的bumpf

public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the bottom bar and the top bar (weird)
    BottomAppBar bottomBar = findViewById(R.id.bottom_app_bar_help);
    Menu bottomMenu = bottomBar.getMenu();
    getMenuInflater().inflate(R.menu.bottom_nav_menu, bottomMenu);
    for (int i = 0; i < bottomMenu.size(); i++) {
        bottomMenu.getItem(i).setOnMenuItemClickListener(item -> {
            if (item.getItemId()==R.id.action_favorite){
                item.setChecked(!item.isChecked());
                // Keep the popup menu open
                item.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
                item.setActionView(new View(frmMain.this));
                item.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
                    @Override
                    public boolean onMenuItemActionExpand(MenuItem item) {
                        final Handler handler = new Handler();
                        handler.postDelayed(() -> bottomMenu.close(), 500);
                        return false;
                    }

                    @Override
                    public boolean onMenuItemActionCollapse(MenuItem item) {
                        final Handler handler = new Handler();
                        handler.postDelayed(() -> bottomMenu.close(), 500);
                        return false;
                    }
                });
                return false;
            }
            else {
                return onOptionsItemSelected(item);
            }
        });
    }
    return true;
}

其他菜单事件在这里

public boolean onOptionsItemSelected(MenuItem item) {
    // Bottom Bar item click
    try {
        switch (item.getItemId()) {
            case R.id.mnuExit:
                MenuClick(ClickType.LOGOUT);
                return true;

            case R.id.mnuList:
                MenuClick(ClickType.LIST);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return super.onOptionsItemSelected(item);
}
于 2019-08-30T10:19:59.687 回答