Bagaimana cara menutup Snackbar menggunakan tombol Tindakannya sendiri?

94

Pustaka dukungan desain Android sekarang menyertakan dukungan untuk Snackbar.

Saya telah menggunakan kode berikut untuk membuatnya:

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

            }
        }).show();

Snackbar dapat ditutup dengan gesekan. Namun, saya juga ingin menutupnya menggunakan Tombol Tindakannya sendiri (dibuat menggunakan fungsi setAction).

Namun tampaknya tidak ada fungsi yang tersedia yang dapat melakukan itu.

Asim
sumber
4
Sebagai catatan bagi orang-orang yang datang ke sini, melakukan tindakan "Singkirkan" di situs Snackbarini bertentangan dengan Pedoman Desain Material Google .
Loyalar

Jawaban:

147

Untuk Java,

The .makeMetode mengembalikan Snackbarobjek. Simpan sebuah instance dari objek itu dengan membuatnya final. Kemudian, di onClick(), panggil .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();

Untuk Kotlin,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()
EE66
sumber
2
jika saya melakukan ini dalam layout koordinator dengan FloatingActionButton, FloatingActionButton tidak turun.
Vinay W
61
Snackbar ditutup secara default saat mengklik tindakan. Memanggil metode penutupan secara eksplisit tidak diperlukan.
Mark Buikema
9
@MarkBuikema fitur ini ditambahkan kemudian. Pada saat itu pertanyaan itu bukanlah perilaku tuli snackbar.
EE66
JFYI, tindakan tidak akan ditampilkan jika OnClickListenerisnull
crgarridos
Mulai hari ini, kode ini akan memanggil tutup dua kali dengan nilai kejadian yang berbeda, satu untuk mengklik tindakan dan satu lagi untuk memanggil dissmiss () secara programatik.
Juan
53

Menerapkan tindakan klik dan biarkan kosong. Mengklik tindakan klik kosong akan menutup snackbar.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();
Ali Zarei
sumber
Anda dapat lulus nulluntuk pendengar, tidak perlu membuat contoh sebenarnya
ccpizza
11

Ketika Anda menggunakan Snackbar.LENGTH_LONGAnda tidak perlu tombol tindakan untuk memberhentikan, setelah kedua secara otomatis memberhentikan. Anda harus menggunakan kode ini:

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

Hati-hati baris ini :

Snackbar.LENGTH_INDEFINITE
golbahar hamed
sumber
6

Ini adalah pertanyaan lama, tetapi saya hanya ingin berbagi pengalaman saya tentang fitur serupa di Snackbar. Jadi kami mendapat desain untuk aplikasi kami, snackbar itu harus ditampilkan tanpa batas waktu dan pengguna harus dapat menutupnya .. tetapi tidak boleh ada tombol DISMISS di dalamnya (Google tidak merekomendasikan tindakan Dismiss atau Cancel di dalam snackbar). Snackbar kami harus dihilangkan hanya dengan mengetuknya.

Satu-satunya solusi, yang berfungsi untuk kami, adalah pada akhirnya (Saya menggunakan retrolambda di sini, tetapi View.OnClickListener standar juga dapat digunakan):

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

Perhatikan panggilan getView () di tengah.

Dariusz Wiechecki
sumber
Di mana Anda membaca bahwa "Google tidak merekomendasikan tindakan Singkirkan atau Batalkan di dalam Snackbars"? Saya ingin membaca alasannya ....
JoseF
@JoseF Silakan periksa komentar pertama di bawah pertanyaan itu sendiri;) Ini ada dalam pedoman Desain Material: material.io/guidelines/components/… ("0-1 tindakan, bukan mengabaikan atau membatalkan")
Dariusz Wiechecki
Jawaban ini unik karena memberikan cara untuk menutup snackbar yang disetel ke 'LENGTH_INDEFINITE' (sehingga pengguna punya waktu untuk membacanya) tanpa harus memulai tindakan apa pun saat tombol tindakan dimulai. Saya menggunakan Snackbar untuk memberi tahu pemain saya bahwa pembaruan telah diunduh dan memulai ulang jika mereka ingin menerapkannya. Jika mereka belum siap untuk memulai kembali, saya ingin cara untuk menutupnya tanpa menekan tombol tindakan. Snackbar di perangkat pengujian saya tidak ditutup dengan gesekan. Kode ini menutupnya dengan sentuhan di luar tombol tindakan, yang seharusnya menjadi perilaku default menurut saya
Androidcoder
3

Snackbar (dari 'com.android.support:design:23.2.1' ) mendukung banyak jenis tindakan pemecatan. Anda dapat membuat filter sederhana dengan menggunakan event , seperti dalam contoh ini:

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

Jenis penutupan 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 Dalam kode sampel digunakan ekspresi lambda (oleh RetroLambda)

a. hitam13
sumber
Pertanyaannya bukan tentang penangan pemecatan. Pertanyaannya adalah bagaimana cara menutup klik tombol.
Jan
2

Saya memiliki masalah yang sama. Ketika saya menggunakan .dismiss () animasinya terlihat berbeda dan ada dua masalah:

  1. FAB tidak turun lagi
  2. SnackBar itu sendiri tidak meluncur ke bawah seperti pada Klik

Melihat ke Kode Sumber Android asli untuk Snackbar saya menemukan solusi berikut:

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

Kemudian, saya akan memanggil .performClick pada snackBarActionButton

snackBarActionButton.performClick();

Tautan ke Kode Sumber Android untuk Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

kiting_and_coding
sumber
Tidak masuk akal bagiku. Mengapa Anda harus memanggil performClick () jika Anda benar-benar mengeklik tombol? Itu sepertinya tidak masuk akal.
Jan