70 votes

Élément de menu vérifiable Android

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

Le 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 autour de l'élément, non ? Pour indiquer qu'il est vérifiable.

Est-ce que je fais quelque chose de mal ?

2 votes

Il suffit de définir non pas Android:checkable à "true", mais Android:checked !

86voto

Sergey Glotov Points 8390

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 respective pour l'élément sélectionné (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 d'état automatiquement. Vous pouvez demander l'état actuel de l'élément (tel qu'il était avant que l'utilisateur ne le sélectionne) à l'aide de la commande isChecked() et ensuite définir l'état vérifié avec setChecked() .

42voto

Gabriel Negut Points 6081

Enveloppez le item dans un 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>

De la Docs Android :

L'attribut Android:checkableBehavior accepte soit :

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

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

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

27voto

hsigmond Points 1795

Vous pouvez créer un élément de menu vérifiable en définissant l'option actionViewClass à un widget vérifiable comme android.widget.CheckBox

res/menu/ menu_avec_élément_de_menu_contrôlable.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 soit une étoile vérifiable si vous mettez actionLayout à 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_avec_étoile_contrôlable_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()

Conversion de MenuItem en CheckBox

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

4voto

Thomas Blake Points 61

J'ai trouvé que la meilleure solution était d'utiliser la méthode onOptionsItemSelected() de mon API actuelle (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);
   }

J'ai passé beaucoup trop de temps ici pour trouver cette réponse et, pour une raison quelconque, les réponses ci-dessus n'ont pas aidé (je suis un nouveau venu et j'ai probablement raté quelque chose, j'en suis sûr). Il pourrait y avoir une meilleure façon de faire, alors toute critique utile est la bienvenue.

1voto

Mr Heelis Points 1167

LIRE CE QUI SUIT

Comme cela a été dit, la "vérification manuelle" n'est que la partie émergée de l'iceberg. Le menu défile si vite les utilisateurs ne voient rien se passer et c'est très contre-intuitif, frustrant, et en fait de la merde totale. Le site REAL TASK (donc) permet à l'événement de la case à cocher d'être digéré par l'esprit des utilisateurs.

Bonne nouvelle : cette peut être fait et ça marche et c'est comme ça qu'il faut faire. @TouchBoarder a eu le meilleur, je vais donc copier son code, puis le développer.

l'idée est de détecter si la case à cocher est cliquée, puis (et seulement si celle-ci est choisie) de supprimer légèrement la suppression du menu, d'ajouter une minuterie pendant 500 ms puis de fermer le menu, ce qui donne à l'animation "tick" de la case à cocher le temps de se dérouler 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>

puis tu fais cette méthode comme d'habitude, mais tu t'assures d'ajouter tout ce bumpf supplémentaire

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X