¿Cómo descartar una Snackbar usando su propio botón de Acción?

93

La biblioteca de soporte de diseño de Android ahora incluye soporte para Snackbar.

He usado el siguiente código para crear uno:

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

            }
        }).show();

El snackbar se puede cerrar con solo deslizar el dedo. Sin embargo, también quiero descartarlo usando su propio Botón de Acción (creado usando la función setAction).

Sin embargo, no parece haber ninguna función disponible que pueda hacer eso.

Asim
fuente
4
Como nota para las personas que vienen aquí, realizar una acción de "Descartar" en el Snackbarestá en contra de las Directrices de diseño de materiales de Google .
Loyalar
Específicamente: material.io/design/components/snackbars.html#usage
Brian Stewart

Respuestas:

145

Para Java,

El .makemétodo devuelve un Snackbarobjeto. Guarde una instancia de ese objeto haciéndolo final. Luego, en el onClick(), llame a .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();

Para Kotlin,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()
EE66
fuente
2
si hago esto en un diseño de coordinador con FloatingActionButton, FloatingActionButton no desciende.
Vinay W
60
Un snackbar se descarta de forma predeterminada al hacer clic en la acción. No es necesario llamar explícitamente al método de descarte.
Mark Buikema
9
@MarkBuikema esta característica se agregó más adelante. En el momento de la pregunta ese no era el comportamiento sordo del snackbar.
EE66
JFYI, la acción no se mostrará si OnClickListeneresnull
crgarridos
A partir de hoy, este código llamará a despedir dos veces con un valor de evento diferente, uno para hacer clic en la acción y otro para llamar a dismiss () mediante programación.
Juan
52

Implemente una acción de clic y deje que se vacíe. Al hacer clic en la acción de clic vacía, se cerrará la barra de bocadillos.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Ali Zarei
fuente
puede pasar nullpor un oyente, no es necesario crear una instancia real
ccpizza
11

Cuando lo usa Snackbar.LENGTH_LONG, no necesita el botón de acción para descartar, después de un segundo descartar automáticamente. Debes usar este código:

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

Tenga cuidado con esta línea :

Snackbar.LENGTH_INDEFINITE
hamed golbahar
fuente
5

Esta es una pregunta antigua, pero solo quiero compartir mi propia experiencia con una función similar en Snackbar. Así que obtuvimos un diseño para nuestra aplicación, esa barra de bocadillos debería mostrarse indefinidamente y el usuario debería poder descartarla ... pero no debería haber un botón DESCARTAR dentro de ella (Google no recomienda las acciones de Descartar o Cancelar dentro de las barras de bocadillos de todos modos). Nuestro snack bar tuvo que ser despedido con solo tocarlo.

La única solución, que funcionó para nosotros, fue al final (estoy usando retrolambda aquí, pero también se podría usar View.OnClickListener estándar):

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

Tenga en cuenta la llamada getView () en el medio.

Dariusz Wiechecki
fuente
¿Dónde lees que "Google no recomienda descartar o cancelar acciones dentro de Snackbars"? Me gustaría leer el motivo ....
JoseF
@JoseF Por favor, marque el primer comentario debajo de la pregunta;) Está en las pautas de Material Design: material.io/guidelines/components/… ("0-1 acciones, no descartar ni cancelar")
Dariusz Wiechecki
3

Snackbar (de 'com.android.support:design:23.2.1' ) admite muchos tipos de acciones de descarte. Puede crear un filtro simple usando evento , como en este ejemplo:

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

Tipos de descarte 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 En el código de muestra se utilizaron expresiones lambda (por RetroLambda)

a.black13
fuente
La pregunta no se trata de un controlador de despido. La pregunta es cómo descartar al hacer clic en el botón.
El increíble
2

Yo tuve el mismo problema. Cuando usé .dismiss (), las animaciones se veían diferentes y había dos problemas:

  1. FAB no vuelve a bajar
  2. el SnackBar en sí no se desliza hacia abajo como lo haría con un clic

Buscando en el código fuente original de Android para Snackbar, encontré la siguiente solución:

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

Luego, llamaría a .performClick en snackBarActionButton

snackBarActionButton.performClick();

Enlace al código fuente de Android para Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
fuente
No tiene ningún sentido para mí. ¿Por qué debería llamar a performClick () si realmente hace clic en un botón? Eso parece una tontería.
El increíble