Como descartar um Snackbar usando seu próprio botão de ação?

93

A biblioteca de suporte de design do Android agora inclui suporte para Snackbar.

Usei o seguinte código para criar um:

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

            }
        }).show();

A lanchonete pode ser descartada com um toque. No entanto, também quero descartá-lo usando seu próprio botão de ação (criado com a função setAction).

No entanto, não parece haver nenhuma função disponível que faça isso.

Asim
fonte
4
Como uma observação para as pessoas que vêm aqui, fazer uma ação de "Dispensar" no Snackbaré contra as Diretrizes de design de materiais do Google .
Loyalar

Respostas:

145

Para Java,

O .makemétodo retorna um Snackbarobjeto. Salve uma instância desse objeto criando-o final. Então, no onClick(), ligue para .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
fonte
2
se eu fizer isso em um layout de coordenador com um FloatingActionButton, o FloatingActionButton não será desativado.
Vinay W
60
Uma barra de ferramentas é descartada por padrão ao clicar na ação. Chamar explicitamente o método de rejeição é desnecessário.
Mark Buikema
9
@MarkBuikema esse recurso foi adicionado mais tarde. Na hora da pergunta esse não era o comportamento surdo da lanchonete.
EE66
JFYI, a ação não será exibida se OnClickListenerfornull
crgarridos
A partir de hoje, esse código chamará dispensa duas vezes com valor de evento diferente, uma para clicar na ação e outra para chamar dissmiss () programaticamente.
Juan
52

Implemente uma ação de clique e deixe-a em branco. Clicar na ação de clique vazia dispensará a barra de ferramentas.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Ali Zarei
fonte
você pode passar nullpor um ouvinte, sem necessidade de criar uma instância real
ccpizza
11

Quando você usa Snackbar.LENGTH_LONGvocê não precisa de botão de ação para dispensar, após o segundo dispensar automaticamente. Você deve 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();

Cuidado com esta linha :

Snackbar.LENGTH_INDEFINITE
hamed golbahar
fonte
5

Esta é uma pergunta antiga, mas eu só quero compartilhar minha própria experiência em torno de recursos semelhantes no Snackbar. Portanto, temos um design para nosso aplicativo, que a barra de ferramentas deve ser exibida indefinidamente e o usuário deve ser capaz de dispensá-la ... mas não deve haver o botão DISMISS dentro dela (o Google não recomenda as ações Dispensar ou Cancelar nas barras de qualquer maneira). Nossa lanchonete teve que ser descartada apenas tocando nela.

A única solução, funcionando para nós, foi no final (estou usando retrolambda aqui, mas o View.OnClickListener padrão também poderia ser usado):

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

Observe a chamada getView () no meio.

Dariusz Wiechecki
fonte
Onde você leu que "o Google não recomenda as ações de dispensar ou cancelar dentro do Snackbars"? Eu gostaria de ler o motivo ....
JoseF
@JoseF Por favor, verifique o primeiro comentário sob a própria pergunta;) Está nas diretrizes do Material Design: material.io/guidelines/components/… ("0-1 ações, não dispensar ou cancelar")
Dariusz Wiechecki
3

Snackbar (de 'com.android.support:design:23.2.1' ) suporta muitos tipos de ação de dispensar. Você pode criar um filtro simples usando evento , como neste exemplo:

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 dispensa do 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 No código de amostra usado expressões lambda (por RetroLambda)

a.black13
fonte
A questão não é sobre um manipulador de dispensa. A questão é como dispensar no clique do botão.
O incrível janeiro
2

Eu tive o mesmo problema. Quando usei .dismiss (), as animações pareciam diferentes e havia dois problemas:

  1. FAB não desce mais
  2. o SnackBar em si não desliza como faria com um clique

Olhando para o código-fonte do Android original para Snackbar, encontrei a seguinte solução:

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

Então, eu chamaria o .performClick no snackBarActionButton

snackBarActionButton.performClick();

Link para o código-fonte do Android para Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
fonte
Não faz sentido para mim. Por que você deve chamar performClick () se realmente clicar em um botão? Isso parece um absurdo.
O incrível janeiro