Comment supprimer un Snackbar en utilisant son propre bouton Action?

93

La bibliothèque de prise en charge de la conception Android inclut désormais la prise en charge de Snackbar.

J'ai utilisé le code suivant pour en créer un:

Snackbar.make(findViewById(R.id.root_layout), result, Snackbar.LENGTH_LONG)
        .setAction("Dismiss", new View.OnClickListener() {
            @Override
            public void onClick(View v) {

            }
        }).show();

Le snack-bar peut être rejeté par un glissement. Cependant, je souhaite également le rejeter en utilisant son propre bouton d'action (créé à l'aide de la fonction setAction).

Cependant, il ne semble y avoir aucune fonction disponible qui puisse faire cela.

Asim
la source
4
En guise de note aux personnes qui viennent ici, effectuer une action "Ignorer" sur le Snackbarest contraire aux directives de conception de matériel de Google .
Loyalar
Plus précisément: material.io/design/components/snackbars.html#usage
Brian Stewart

Réponses:

145

Pour Java,

La .makeméthode renvoie un Snackbarobjet. Enregistrez une instance de cet objet en le créant final. Ensuite, dans le onClick(), appelez .dismiss:

final Snackbar snackBar = Snackbar.make(findViewById(android.R.id.content), "Snackbar Message", Snackbar.LENGTH_LONG);

        snackBar.setAction("Action Message", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Call your action method here
                snackBar.dismiss();
            }
        });
        snackBar.show();

Pour Kotlin,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()
EE66
la source
2
si je fais cela dans une mise en page de coordination avec un FloatingActionButton, le FloatingActionButton ne descend pas.
Vinay W
60
Un snack est supprimé par défaut lorsque vous cliquez sur l'action. L'appel explicite de la méthode de rejet n'est pas nécessaire.
Mark Buikema
9
@MarkBuikema cette fonctionnalité a été ajoutée plus tard. Au moment de la question ce n'était pas le comportement sourd du snack.
EE66
JFYI, l'action ne sera pas affichée si le OnClickListenerestnull
crgarridos
À partir d'aujourd'hui, ce code appellera rejeter deux fois avec une valeur d'événement différente, une pour cliquer sur l'action et une autre pour appeler dissmiss () par programme.
Juan
52

Implémentez une action de clic et laissez-la se vider. Cliquer sur l'action de clic vide fera disparaître le snack.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Ali Zarei
la source
vous pouvez passer nullpour un auditeur, pas besoin de créer une instance réelle
ccpizza
11

Lorsque vous utilisez, Snackbar.LENGTH_LONGvous n'avez pas besoin de bouton d'action pour ignorer, après la seconde, rejetez automatiquement. Vous devez utiliser ce code:

 Snackbar snackbar = Snackbar.make(relativeLayout, "Your Message", Snackbar.LENGTH_INDEFINITE);
            snackbar.setAction("dismiss", new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    snackbar.dismiss();
                }
            });

            snackbar.show();

Faites attention à cette ligne :

Snackbar.LENGTH_INDEFINITE
golbahar haché
la source
5

C'est une vieille question, mais je veux juste partager ma propre expérience autour d'une fonctionnalité similaire sur Snackbar. Nous avons donc eu un design pour notre application, ce snack-bar devrait être affiché indéfiniment et l'utilisateur devrait pouvoir le rejeter ... mais il ne devrait pas y avoir de bouton DISMISS à l'intérieur (Google ne recommande de toute façon pas de rejeter ou d'annuler les actions dans les snackbars). Notre snack a dû être rejeté simplement en appuyant dessus.

La seule solution, qui fonctionnait pour nous, était à la fin (j'utilise retrolambda ici, mais View.OnClickListener standard pourrait également être utilisé):

final Snackbar snack = ... /* create proper snackbar as alway */
snack.getView().setOnClickListener(v -> snack.dismiss());

Notez l' appel getView () au milieu.

Dariusz Wiechecki
la source
Où lisez-vous que "Google ne recommande pas de rejeter ou d'annuler les actions dans Snackbars"? Je voudrais lire la raison ....
JoseF
@JoseF S'il vous plaît vérifier le premier commentaire sous la question elle-même;) C'est dans les directives de conception matérielle : material.io/guidelines/components/... ("0-1 actions, ne pas rejeter ou annuler")
Dariusz Wiechecki
3

Snackbar (de 'com.android.support:design:23.2.1' ) prend en charge de nombreux types d'action de licenciement. Vous pouvez créer un filtre simple en utilisant un événement , comme dans cet exemple:

Snackbar.make(view, wornMessage, Snackbar.LENGTH_LONG).setActionTextColor(context.getResources().getColor(R.color.primary))
    .setCallback(new Snackbar.Callback() {
        @Override
        public void onShown(Snackbar snackbar) {
            super.onShown(snackbar);
        // when snackbar is showing
        }

        @Override
        public void onDismissed(Snackbar snackbar, int event) {
            super.onDismissed(snackbar, event);
            if (event != DISMISS_EVENT_ACTION) {
               //will be true if user not click on Action button (for example: manual dismiss, dismiss by swipe
            }
        }
    })
    .setAction("Undo, view1 -> {
        // if user click on Action button
}).show();

Types de rejet de Snackbar:

/** Indicates that the Snackbar was dismissed via a swipe.*/
public static final int DISMISS_EVENT_SWIPE = 0;
/** Indicates that the Snackbar was dismissed via an action click.*/
public static final int DISMISS_EVENT_ACTION = 1;
/** Indicates that the Snackbar was dismissed via a timeout.*/
public static final int DISMISS_EVENT_TIMEOUT = 2;
/** Indicates that the Snackbar was dismissed via a call to {@link #dismiss()}.*/
public static final int DISMISS_EVENT_MANUAL = 3;
/** Indicates that the Snackbar was dismissed from a new Snackbar being shown.*/
public static final int DISMISS_EVENT_CONSECUTIVE = 4;

PS Dans l'exemple de code utilisé des expressions lambda (par RetroLambda)

a.black13
la source
La question ne concerne pas un gestionnaire de rejet. La question est de savoir comment ignorer un clic sur un bouton.
L'incroyable janvier
2

J'ai eu le même problème. Quand j'ai utilisé .dismiss (), les animations étaient différentes et il y avait deux problèmes:

  1. FAB ne redescend plus
  2. le SnackBar lui-même ne glisse pas comme il le ferait sur un clic

En regardant dans le code source Android original pour Snackbar, j'ai trouvé la solution suivante:

View snackbarView = snackbar.getView();
Button snackbarActionButton = (Button) snackbarView.findViewById(android.support.design.R.id.snackbar_action);
//snackbarActionButton.setSoundEffectsEnabled(false); // might be considered in order not to have a confusing sound because nothing was clicked by the user

Ensuite, j'appellerais le .performClick sur le snackBarActionButton

snackBarActionButton.performClick();

Lien vers le code source Android pour Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
la source
Cela n'a aucun sens pour moi. Pourquoi devriez-vous appeler performClick () si vous cliquez réellement sur un bouton? Cela semble absurde.
L'incroyable janvier