Jak odrzucić Snackbar za pomocą własnego przycisku akcji?

94

Biblioteka wsparcia projektowania Androida obejmuje teraz obsługę Snackbar.

Użyłem następującego kodu, aby go utworzyć:

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

            }
        }).show();

Pasek z przekąskami można zamknąć jednym machnięciem. Jednak chcę również odrzucić go za pomocą własnego przycisku akcji (utworzonego za pomocą funkcji setAction).

Jednak wydaje się, że nie ma żadnej dostępnej funkcji, która mogłaby to zrobić.

Asim
źródło
4
Uwaga dla przyjeżdżających tutaj osób, że wykonanie czynności „Odrzuć” w witrynie Snackbarjest niezgodne z wytycznymi Google Material Design .
Loyalar
W szczególności: material.io/design/components/snackbars.html#usage
Brian Stewart,

Odpowiedzi:

147

W przypadku Javy

.makeSposób powraca do Snackbarobiektu. Zapisz instancję tego obiektu, tworząc ją final. Następnie onClick()zadzwoń .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();

Dla Kotlina,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()
EE66
źródło
2
jeśli zrobię to w układzie koordynatora z FloatingActionButton, FloatingActionButton nie zejdzie.
Vinay W
61
Po kliknięciu działania pasek przekąsek jest domyślnie odrzucany. Jawne wywołanie metody odrzucenia jest niepotrzebne.
Mark Buikema
9
@MarkBuikema ta funkcja została dodana później. W chwili pytania nie było to głuche zachowanie baru z przekąskami.
EE66
JFYI, akcja nie zostanie pokazana, jeśli OnClickListenerjestnull
crgarridos
Od dzisiaj ten kod wywoła odrzucenie dwukrotnie z różną wartością zdarzenia, jedno do kliknięcia akcji, a drugie do programowego wywoływania dissmiss ().
Juan
53

Zaimplementuj akcję kliknięcia i pozostaw ją pustą. Kliknięcie pustego kliknięcia spowoduje zamknięcie paska przekąskowego.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Ali Zarei
źródło
możesz uchodzić nullza słuchacza, nie musisz tworzyć rzeczywistej instancji
ccpizza
11

Kiedy używasz Snackbar.LENGTH_LONG, nie potrzebujesz przycisku akcji do zwolnienia, po drugim automatycznie odrzuć. Powinieneś użyć tego kodu:

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

Uważaj na tę linię :

Snackbar.LENGTH_INDEFINITE
hamed golbahar
źródło
6

To stare pytanie, ale chcę tylko podzielić się własnym doświadczeniem na temat podobnej funkcji w Snackbar. Mamy więc projekt naszej aplikacji, który powinien być wyświetlany w nieskończoność, a użytkownik powinien mieć możliwość jego odrzucenia… ale w środku nie powinien znajdować się przycisk ODRZUĆ (Google i tak nie zaleca akcji Odrzuć lub Anuluj wewnątrz batonów). Nasz bar z przekąskami musiał zostać usunięty po prostu przez dotknięcie go.

Jedynym rozwiązaniem, które u nas działało, było w końcu (używam tutaj retrolambda, ale można użyć standardowego View.OnClickListener):

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

Zwróć uwagę na wywołanie getView () w środku.

Dariusz Wiechecki
źródło
Gdzie czytasz, że „Google nie zaleca Odrzuć lub Anuluj działania w Snackbarach”? Chciałbym przeczytać powód ...
JoseF,
@JoseF Proszę sprawdzić pierwszy komentarz pod samym pytaniem;) Jest w wytycznych Material Design: material.io/guidelines/components/ ... („Akcje 0-1, nie odrzucaj ani nie anuluj”)
Dariusz Wiechecki
Ta odpowiedź jest wyjątkowa, ponieważ umożliwia odrzucenie paska przekąskowego ustawionego na „LENGTH_INDEFINITE” (dzięki czemu użytkownik ma czas na przeczytanie) bez konieczności rozpoczynania czynności, którą uruchamia przycisk akcji. Używam Snackbar, aby powiadomić moich graczy, że aktualizacja została pobrana i aby ponownie uruchomić, jeśli chcą, aby została zaimplementowana. Jeśli nie są gotowe do ponownego uruchomienia, szukałem sposobu, aby je zamknąć bez naciskania przycisku akcji. Snackbary na moich urządzeniach testowych nie są usuwane jednym machnięciem. Ten kod odrzuca go dotknięciem poza przyciskiem akcji, co powinno być moim zdaniem domyślnym zachowaniem
Androidcoder
3

Snackbar (z „com.android.support:design:23.2.1” ) obsługuje wiele typów akcji zwolnienia. Możesz utworzyć prosty filtr, używając zdarzenia , takiego jak w tym przykładzie:

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

Typy zwolnień 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 W przykładowym kodzie wykorzystano wyrażenia lambda (autorstwa RetroLambda)

a. czarny 13
źródło
Pytanie nie dotyczy osoby obsługującej zwolnienia. Pytanie brzmi, jak odrzucić po kliknięciu przycisku.
Niesamowity
2

Miałem ten sam problem. Kiedy użyłem .dismiss (), animacje wyglądały inaczej i były dwa problemy:

  1. FAB nie spada ponownie
  2. sam SnackBar nie zsuwa się tak, jak przy kliknięciu

Patrząc na oryginalny kod źródłowy Androida dla Snackbar, znalazłem następujące rozwiązanie:

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

Następnie nazwałbym .performClick na snackBarActionButton

snackBarActionButton.performClick();

Link do kodu źródłowego Androida dla Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
źródło
Nie ma to dla mnie żadnego sensu. Dlaczego miałbyś wywoływać performClick (), jeśli faktycznie klikasz przycisk? To wydaje się być nonsensem.
Niesamowity