Элемент меню Android с возможностью проверки

У меня есть следующий макет меню в моем приложении для 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. У пункта должна быть зеленая галочка, верно? Чтобы указать, что его можно проверить.

Я делаю что-то неправильно?


person Icemanind    schedule 04.06.2011    source источник
comment
Вам просто нужно установить не android:checkable в true, а android:checked !   -  person Felix Julian    schedule 24.05.2015


Ответы (9)


Макет выглядит правильно. Но вы должны проверить и снять флажок с пункта меню в коде.

Из документации:

Когда выбранный элемент выбран, система вызывает соответствующий метод обратного вызова для выбранного элемента (например, onOptionsItemSelected()). Именно здесь вы должны установить состояние флажка, потому что флажок или переключатель не меняют свое состояние автоматически. Вы можете запросить текущее состояние элемента (каким оно было до того, как его выбрал пользователь) с помощью isChecked(), а затем установите проверенное состояние с помощью setChecked().

person Sergey Glotov    schedule 04.06.2011
comment
Прямо над этой цитатой написано You can apply a default checked state to an item using the android:checked attribute in the <item> element and change it in code with the setChecked() method. Какой из них правильный? - person Gabriel Negut; 05.06.2011
comment
Я не вижу, что не так. В этой цитате сказано, что может быть применено состояние проверки по умолчанию и состояние проверки может быть изменено. В моей цитате сказано, что состояние проверки нужно менять вручную по коду. - person Sergey Glotov; 05.06.2011
comment
Мой плохой на этом .. Меня смутило начальное состояние пунктов меню, нужно ли его устанавливать из кода или нет. Похоже, что начальное проверенное состояние может быть установлено из xml, а после может быть изменено по желанию из кода, это правильно? - person Gabriel Negut; 05.06.2011
comment
Да, как только я применил Java-код для программной проверки и снятия отметки с элемента и сохранил состояние, у меня это сработало, что делает Сергея победителем. Спасибо! - person Icemanind; 05.06.2011
comment
Спасибо за предложение. Как мы можем оставить меню открытым после его проверки? - person Srikar Reddy; 29.08.2015
comment
Обратите внимание, что пример кода, приведенный ниже этой цитаты, не работает. - person The Berga; 14.04.2016

Оберните 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 принимает:

single - можно отметить только один элемент из группы (переключатели)

all - Все элементы могут быть отмечены (флажками)

none - нет элементов, которые можно проверить

person Gabriel Negut    schedule 04.06.2011

Вы можете создать пункт меню с возможностью проверки, установив 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

res/layout /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();
person TouchBoarder    schedule 22.03.2016
comment
наконец - рабочий код!! Мне потребовалось два часа, чтобы найти то, что работает! Меню не должно быть таким чертовски сложным!! app:actionViewClass — это место для флажков в меню. - person Someone Somewhere; 23.04.2019
comment
получается, что это на самом деле нехорошо, потому что чекбокс не является частью пункта меню; пользователь щелкнет текст, а флажок останется нетронутым - при условии, что я могу изменить это программно. ОДНАКО, когда пользователь касается только флажка, проклятый onNavigationItemSelected() не срабатывает. - person Someone Somewhere; 23.04.2019
comment
на данный момент я не могу рекомендовать использование меню в панели навигации - если вам нужны флажки. Это все виды сломал! Я собираюсь добавить флажки вручную под меню. - person Someone Somewhere; 23.04.2019
comment
Я добавил задержку прерывания 300 мс hide при исчезновении меню (только если они нажали флажок).. Я раскопаю код.. выглядит нормально - person Mr Heelis; 30.08.2019

Я обнаружил, что лучшим решением было просто использовать метод onOptionsItemSelected() в моем текущем API (27-28).

@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);
   }

Я потратил много времени здесь на этот ответ. и по какой-то причине приведенные выше ответы не помогли (я вернувшийся новичок, я, наверное, что-то испортил, я уверен). Можно было бы сделать это лучше, поэтому полезная критика приветствуется.

person Thomas Blake    schedule 06.06.2020

Отвечаю, потому что ответы здесь кажутся длинными и запутанными. У меня есть точный код 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>
person Rowan Berry    schedule 07.10.2019

Это может зависеть от темы, но в моем меню не было флажка. Я нашел это:

Примечание. Элементы меню в меню значков не могут отображать флажки или переключатели. Если вы решите сделать элементы в меню значков доступными для проверки, то вы должны лично указывать состояние, меняя местами значок и/или текст каждый раз, когда состояние меняется с включенного на выключенное.

person sham    schedule 05.06.2014

Для добавления пунктов меню программно,

@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" />
person Lins Louis    schedule 09.03.2018

ПРОЧИТАЙТЕ ЭТО

Как уже было сказано, «ручная проверка» — это только вершина айсберга. Он высвечивает меню так быстро, пользователи не видят, что происходит, и это очень нелогично, раздражает и, по сути, является полной чушью. REAL TASK (поэтому) позволяет пользователю переваривать событие флажка.

Хорошие новости: это можно сделать, и это действительно работает, и вот как вы это делаете. У @TouchBoarder было лучше, поэтому я скопирую его код. затем развивать его.

идея состоит в том, чтобы определить, нажат ли флажок, а затем (и только если он выбран) слегка подавить удаление меню, добавить таймер на 500 мс, а затем закрыть меню, это дает время для запуска анимации «тик» флажка и создает правильное «ощущение»

<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>

затем вы делаете этот метод, как обычно, но обязательно добавляете все эти дополнительные удары

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);
}
person Mr Heelis    schedule 30.08.2019

У меня есть два пункта в меню, и я установил их для проверки в файле 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);
    }
person user8903954    schedule 23.07.2020