Làm thế nào để loại bỏ một Snackbar bằng nút Hành động của chính nó?


93

Thư viện hỗ trợ thiết kế Android hiện bao gồm hỗ trợ cho Snackbar.

Tôi đã sử dụng mã sau để tạo một mã:

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

            }
        }).show();

Thanh nhanh có thể được loại bỏ bằng cách vuốt. Tuy nhiên, tôi cũng muốn loại bỏ nó bằng cách sử dụng Nút hành động của riêng nó (được tạo bằng cách sử dụng hàm setAction).

Tuy nhiên, dường như không có bất kỳ chức năng nào có thể làm được điều đó.


4
Xin lưu ý những người đến đây, việc thực hiện hành động "Loại bỏ" trên Snackbarlà vi phạm Nguyên tắc thiết kế Material Design của Google .
Loyalar

Câu trả lời:


145

Đối với Java,

Các .makephương thức trả về một Snackbarđối tượng. Lưu một thể hiện của đối tượng đó bằng cách tạo nó final. Sau đó, trong onClick()cuộc gọi .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();

Đối với Kotlin,

        Snackbar.make(
            findViewById(android.R.id.content),
            "Snackbar Message",
            Snackbar.LENGTH_INDEFINITE
        ).setAction("Action Message") {
            // Call action functions here
        }.show()

2
nếu tôi thực hiện việc này trong bố cục bộ điều phối với FloatingActionButton, FloatingActionButton sẽ không đi xuống.
Vinay W

60
Thanh nhanh bị loại bỏ theo mặc định khi nhấp vào hành động. Việc gọi rõ ràng phương thức loại bỏ là không cần thiết.
Mark Buikema

9
@MarkBuikema tính năng này đã được thêm vào sau đó. Vào thời điểm câu hỏi đó không phải là hành vi đáng sợ của thanh ăn nhẹ.
EE66

JFYI, hành động sẽ không được hiển thị nếu OnClickListenernull
crgarridos

Kể từ hôm nay, mã này sẽ gọi loại bỏ hai lần với các giá trị sự kiện khác nhau, một lần để nhấp vào hành động và một lần khác để gọi dissmiss () theo chương trình.
Juan

52

Thực hiện hành động nhấp chuột và để trống. Nhấp vào hành động nhấp trống sẽ loại bỏ thanh nhanh.

Snackbar.make(coordinatorLayoutView, "Service Enabled", Snackbar.LENGTH_LONG)
    .setAction("DISMISS", new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        }
    })
    .show();

bạn có thể chuyển nullcho một người nghe, không cần tạo một phiên bản thực tế
ccpizza

11

Khi bạn sử dụng, Snackbar.LENGTH_LONGbạn không cần nút tác vụ để loại bỏ, sau giây tự động loại bỏ. Bạn nên sử dụng mã này:

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

Hãy cẩn thận dòng này :

Snackbar.LENGTH_INDEFINITE

5

Đây là một câu hỏi cũ, nhưng tôi chỉ muốn chia sẻ kinh nghiệm của riêng tôi về tính năng tương tự trên Snackbar. Vì vậy, chúng tôi đã có một thiết kế cho ứng dụng của mình, thanh ăn nhẹ đó sẽ được hiển thị vô thời hạn và người dùng có thể loại bỏ nó .. nhưng không nên có nút BỎ LỠ bên trong nó (dù sao thì Google cũng không khuyến nghị Bỏ qua hoặc Hủy các hành động bên trong các thanh ăn nhẹ). Thanh ăn nhẹ của chúng tôi đã bị loại bỏ chỉ bằng cách chạm vào nó.

Cuối cùng, giải pháp duy nhất phù hợp với chúng tôi (tôi đang sử dụng retrolambda ở đây, nhưng cũng có thể sử dụng View.OnClickListener tiêu chuẩn):

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

Lưu ý cuộc gọi getView () ở giữa.


Bạn đọc ở đâu rằng "Google không khuyến nghị Bỏ qua hoặc Hủy bỏ các hành động trong Snackbars"? Tôi muốn đọc lý do ....
JoseF 14/09/17

@JoseF Vui lòng kiểm tra nhận xét đầu tiên dưới câu hỏi riêng của mình;) Đó là trong hướng dẫn thiết kế Chất liệu: material.io/guidelines/components/... ( "0-1 hành động, chứ không phải sa thải hoặc hủy")
Dariusz Wiechecki

3

Snackbar (từ 'com.android.support:design:23.2.1' ) hỗ trợ nhiều loại hành động loại bỏ. Bạn có thể tạo một bộ lọc đơn giản bằng cách sử dụng sự kiện , chẳng hạn như trong ví dụ này:

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

Các loại loại bỏ của 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 Trong mã mẫu được sử dụng các biểu thức lambda (bởi RetroLambda)


Câu hỏi không phải về trình xử lý sa thải. Câu hỏi là làm thế nào để loại bỏ khi nhấp vào nút.
Điều đáng kinh ngạc ngày 1 tháng

2

Tôi đã từng gặp vấn đề tương tự. Khi tôi sử dụng .dismiss (), các hoạt ảnh trông khác và có hai vấn đề:

  1. FAB không đi xuống nữa
  2. Bản thân SnackBar không trượt xuống như khi nhấp vào

Xem xét Mã nguồn Android ban đầu cho Snackbar, tôi tìm thấy giải pháp sau:

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

Sau đó, tôi sẽ gọi .performClick trên snackBarActionButton

snackBarActionButton.performClick();

Liên kết đến Mã nguồn Android cho Snackbar: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java


Không có ý nghĩa gì đối với tôi. Tại sao bạn nên gọi PerformClick () nếu bạn thực sự nhấp vào một nút? Điều đó dường như là vô nghĩa.
Điều đáng kinh ngạc ngày 1 tháng
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.