Как закрыть Snackbar с помощью собственной кнопки действия?

94

Библиотека поддержки дизайна Android теперь включает поддержку Snackbar.

Я использовал следующий код для его создания:

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

            }
        }).show();

Закусочную можно закрыть, проведя пальцем по экрану. Однако я также хочу отклонить его с помощью собственной кнопки действия (созданной с помощью функции setAction).

Однако, похоже, нет никакой доступной функции, которая могла бы это сделать.

Асим
источник
4
В качестве примечания для людей, приходящих сюда, действие «Отклонить» Snackbarявляется нарушением рекомендаций Google по дизайну материалов .
Loyalar 08
В частности: material.io/design/components/snackbars.html#usage
Брайан Стюарт,

Ответы:

147

Для Java

.makeМетод возвращает Snackbarобъект. Сохраните экземпляр этого объекта, создав его final. Затем onClick()позвоните в .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();

Для Котлина,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()
EE66
источник
2
если я сделаю это в макете координатора с FloatingActionButton, FloatingActionButton не сработает.
Vinay W
61
По умолчанию закусочная закрывается при нажатии на действие. Явный вызов метода увольнения не требуется.
Марк Буйкема
9
@MarkBuikema эта функция была добавлена ​​позже. Во время вопроса это не было глухим поведением закусочной.
EE66 02
JFYI, действие не будет показано, если OnClickListenerбудетnull
crgarridos
На сегодняшний день этот код будет вызывать отклонение дважды с разными значениями события, одно для щелчка по действию, а другое для программного вызова dismiss ().
Хуан
53

Реализуйте действие щелчка и оставьте его пустым. Щелчок по пустому действию щелчка закроет снэк-бар.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Али Зарей
источник
вы можете сойти nullза слушателя, нет необходимости создавать реальный экземпляр
ccpizza
11

Когда вы используете, Snackbar.LENGTH_LONGвам не нужна кнопка действия для закрытия, через секунду автоматически отклоняется. Вам следует использовать этот код:

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

Будьте осторожны с этой строкой :

Snackbar.LENGTH_INDEFINITE
Хамед Голбахар
источник
6

Это старый вопрос, но я просто хочу поделиться своим опытом использования аналогичной функции на Snackbar. Итак, у нас есть дизайн для нашего приложения, в котором закусочная должна отображаться на неопределенное время, и пользователь должен иметь возможность ее закрыть ... но внутри нее не должно быть кнопки DISMISS (Google в любом случае не рекомендует Dismiss или Cancel внутри закусочных). Наш буфет нужно было закрыть, просто нажав на него.

Единственное решение, сработавшее для нас, было в итоге (я использую здесь retrolambda, но можно использовать и стандартный View.OnClickListener):

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

Обратите внимание на вызов getView () посередине.

Дариуш Вечецкий
источник
Где вы читаете, что «Google не рекомендует отклонять или отменять действия в Snackbars»? Я хотел бы прочесть причину ....
JoseF
@JoseF Пожалуйста, проверьте первый комментарий под самим вопросом;) Он находится в руководстве по материальному дизайну: material.io/guidelines/components/… («Действия 0–1, не отклонять и не отменять»)
Дариуш Вичецки
Этот ответ уникален тем, что он дает возможность отклонить снекбар, для которого установлено значение «LENGTH_INDEFINITE» (чтобы у пользователя было время его прочитать), без необходимости запускать какое-либо действие, которое запускает кнопка действия. Я использую Snackbar, чтобы уведомить своих игроков, что обновление было загружено, и перезапустить, если они хотят, чтобы оно было реализовано. Если они не готовы к перезапуску, мне нужен способ закрыть его, не нажимая кнопку действия. Закуски на моих тестовых устройствах не закрываются одним движением. Этот код отклоняет его одним касанием за пределами кнопки действия, что, на мой взгляд, должно быть поведением по умолчанию
Androidcoder
3

Snackbar (от com.android.support:design:23.2.1 ) поддерживает множество типов действий по закрытию . Вы можете создать простой фильтр, используя событие , как в этом примере:

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

Типы увольнения 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 В примере кода использованы лямбда-выражения (от RetroLambda)

a.black13
источник
Вопрос не в кураторе увольнения. Вопрос в том, как закрыть по нажатию кнопки.
Невероятное
2

У меня такая же проблема. Когда я использовал .dismiss (), анимация выглядела иначе, и возникли две проблемы:

  1. FAB снова не выходит из строя
  2. Сам SnackBar не скользит вниз, как при нажатии

Заглянув в исходный код Android для Snackbar, я нашел следующее решение:

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

Затем я бы назвал .performClick для snackBarActionButton

snackBarActionButton.performClick();

Ссылка на исходный код Android для Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
источник
Для меня это не имеет никакого смысла. Зачем вам вызывать performClick (), если вы действительно нажимаете кнопку? Кажется, это ерунда.
Невероятный