web-dev-qa-db-fra.com

Android Élément de menu vérifiable

J'ai la disposition de menu suivante dans mon 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>

Mon problème est que le deuxième élément du menu ne semble pas être "vérifiable" lorsque j'exécute mon application dans l'émulateur Android. Il devrait y avoir une coche verte à propos de l'élément, non? Pour indiquer que son vérifiable.

Est-ce que je fais quelque chose de mal?

59
Icemanind

La mise en page semble correcte. Mais vous devez cocher et décocher l'élément de menu dans le code.

De la documentation :

Lorsqu'un élément vérifiable est sélectionné, le système appelle votre méthode de rappel sélectionnée par élément respective (telle que onOptionsItemSelected() ). C'est ici que vous devez définir l'état de la case à cocher, car une case à cocher ou un bouton radio ne change pas automatiquement son état. Vous pouvez interroger l'état actuel de l'élément (tel qu'il était avant que l'utilisateur ne le sélectionne) avec isChecked() puis définir l'état vérifié avec setChecked() .

80
Sergey Glotov

Enveloppez les items dans un élément group, comme ceci:

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

Depuis les documents Android :

L'attribut Android: checkableBehavior accepte soit:

single - Un seul élément du groupe peut être vérifié (boutons radio)

all - Tous les éléments peuvent être cochés (cases à cocher)

aucun - Aucun élément n'est vérifiable

32
Gabriel Negut

Vous pouvez créer un élément de menu vérifiable en définissant actionViewClass sur un widget vérifiable comme 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>

Et vous pouvez même le styliser pour qu'il devienne une étoile à cocher si vous définissez actionLayout sur une mise en page avec un style 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>

Pour définir la valeur

menuItem.setChecked(true/false);

Pour obtenir la valeur

menuItem.isChecked()

Cast MenuItem vers CheckBox

CheckBox checkBox= (CheckBox) menuItem.getActionView();
17
TouchBoarder

Pour ajouter des éléments de menu par programme,

@Override
public boolean onCreateOptionsMenu(Menu menu) {

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

res/layout /action_layout_checkbox.xml

<CheckBox xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content" />
0
Lins Louis

Cela peut dépendre du thème, mais mon menu n'affichait aucune case à cocher. J'ai trouvé ceci :

Remarque: les éléments de menu du menu d'icônes ne peuvent pas afficher une case à cocher ou un bouton radio. Si vous choisissez de rendre les éléments du menu d'icônes vérifiables, vous devez alors indiquer personnellement l'état en échangeant l'icône et/ou le texte chaque fois que l'état change entre activé et désactivé.

0
sham

LIRE CECI

Comme on l'a dit, la "vérification manuelle" n'est que la pointe de l'iceberg. Il fait clignoter le menu si rapidement que les utilisateurs ne voient rien se produire et il est très contre-intuitif, frustrant et efficace. Le REAL TASK (donc) permet à l'événement de la case à cocher d'être digéré par l'esprit des utilisateurs.

Bonne nouvelle: ceci peut être fait et cela fonctionne et c'est comme ça que vous le faites. @TouchBoarder l'a mieux fait, je vais donc copier son code. puis développez-le.

l'idée est de détecter si la case est cochée, puis (et seulement si celle-ci est sélectionnée) de supprimer légèrement la suppression du menu, d'ajouter une minuterie pendant 500 ms puis de fermer le menu, cela donne à l'animation "tick" du temps de la case à cocher et crée la bonne "sensation"

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

alors vous faites cette méthode comme d'habitude, mais vous vous assurez d'ajouter tous ces bumpf supplémentaires

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

les autres événements du menu sont ici

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);
}
0
Mr Heelis