Come chiudere uno snackbar utilizzando il proprio pulsante di azione?


93

La libreria di supporto alla progettazione Android ora include il supporto per Snackbar.

Ho usato il seguente codice per crearne uno:

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

            }
        }).show();

Lo snackbar può essere chiuso con un semplice tocco. Tuttavia, desidero anche chiuderlo utilizzando il proprio pulsante di azione (creato utilizzando la funzione setAction).

Tuttavia non sembra esserci alcuna funzione disponibile in grado di farlo.


4
Come nota per le persone che vengono qui, fare un'azione "Ignora" su Snackbarè contro le linee guida di Google Material Design .
Loyalar

Risposte:


145

Per Java,

Il .makemetodo restituisce un Snackbaroggetto. Salva un'istanza di quell'oggetto creandola final. Quindi, nel onClick(), chiama .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();

Per Kotlin,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()

2
se lo faccio in un layout coordinatore con FloatingActionButton, FloatingActionButton non scende.
Vinay W

60
Una snackbar viene chiusa per impostazione predefinita quando si fa clic sull'azione. La chiamata esplicita del metodo dismiss non è necessaria.
Mark Buikema

9
@MarkBuikema questa funzione è stata aggiunta in seguito. Al momento della domanda quello non era il comportamento sordo dello snack bar.
EE66

JFYI, l'azione non verrà mostrata se OnClickListenerènull
crgarridos

Ad oggi, questo codice chiamerà dismiss due volte con un valore di evento diverso, uno per fare clic sull'azione e un altro per chiamare dissmiss () in modo programmatico.
Juan

52

Implementa un'azione di clic e lasciala vuota. Facendo clic sull'azione clic vuoto si chiuderà la snackbar.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();

puoi passare nullper un ascoltatore, non c'è bisogno di creare un'istanza reale
ccpizza

11

Quando si utilizza Snackbar.LENGTH_LONGnon è necessario il pulsante di azione per l'eliminazione, dopo il secondo si elimina automaticamente. Dovresti usare questo codice:

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

Fai attenzione a questa linea :

Snackbar.LENGTH_INDEFINITE

5

Questa è una vecchia domanda, ma voglio solo condividere la mia esperienza su funzionalità simili su Snackbar. Quindi abbiamo ottenuto un design per la nostra app, quella snackbar dovrebbe essere mostrata a tempo indeterminato e l'utente dovrebbe essere in grado di ignorarla .. ma non dovrebbe esserci il pulsante DISMISS al suo interno (Google non consiglia comunque le azioni Ignora o Annulla all'interno delle snackbars). Il nostro snack bar doveva essere chiuso semplicemente toccandolo.

L'unica soluzione, che ha funzionato per noi, è stata alla fine (sto usando retrolambda qui, ma si potrebbe usare anche lo standard View.OnClickListener):

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

Nota la chiamata getView () al centro.


Dove hai letto che "Google non consiglia le azioni Ignora o Annulla all'interno di Snackbars"? Vorrei leggere il motivo ...
JoseF

@JoseF Si prega di controllare il primo commento sotto la domanda stessa;) È nelle linee guida di Material Design: material.io/guidelines/components/… ("0-1 azioni, non respingere o annullare")
Dariusz Wiechecki

3

Snackbar (da "com.android.support:design:23.2.1" ) supporta molti tipi di azioni di chiusura. È possibile creare un semplice filtro utilizzando event , come in questo esempio:

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

Tipi di licenziamento di 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 Nel codice di esempio sono state utilizzate espressioni lambda (di RetroLambda)


La domanda non riguarda un gestore di licenziamento. La domanda è come ignorare facendo clic sul pulsante.
L'incredibile

2

Ho avuto lo stesso problema. Quando ho usato .dismiss () le animazioni sembravano diverse e c'erano due problemi:

  1. FAB non scende di nuovo
  2. lo SnackBar stesso non scorre verso il basso come farebbe con un clic

Esaminando il codice sorgente Android originale per Snackbar ho trovato la seguente soluzione:

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

Quindi, chiamerei .performClick sullo snackBarActionButton

snackBarActionButton.performClick();

Link al codice sorgente Android per Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java


Non ha alcun senso per me. Perché dovresti chiamare performClick () se fai effettivamente clic su un pulsante? Sembra non avere senso.
L'incredibile
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.