จะปิด Snackbar โดยใช้ปุ่ม Action ได้อย่างไร?


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

คำตอบ:


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

สำหรับ Kotlin

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

2
ถ้าฉันทำสิ่งนี้ในเค้าโครงผู้ประสานงานด้วย FloatingActionButton FloatingActionButton จะไม่ลงมา
Vinay W

61
แถบสแน็คบาร์จะถูกปิดโดยค่าเริ่มต้นเมื่อคลิกที่การกระทำ ไม่จำเป็นต้องเรียกเมธอดการเลิกจ้างอย่างชัดเจน
Mark Buikema

9
@MarkBuikema คุณลักษณะนี้ถูกเพิ่มในภายหลัง ในช่วงเวลาของคำถามที่ไม่ใช่พฤติกรรมของคนหูหนวกของสแน็คบาร์
66

JFYI การกระทำจะไม่ปรากฏหากOnClickListenerเป็นnull
crgarridos

ณ วันนี้รหัสนี้จะเรียกการปิดสองครั้งโดยมีค่าเหตุการณ์ต่างกันค่าหนึ่งสำหรับการคลิกที่การกระทำและอีกอันหนึ่งสำหรับการเรียก dissmiss () โดยทางโปรแกรม
ฮวน

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 ไม่แนะนำให้ปิดหรือยกเลิกการดำเนินการภายในสแน็คบาร์) สแน็คบาร์ของเราต้องถูกยกเลิกเพียงแค่แตะที่มัน

ทางออกเดียวที่ใช้ได้ผลสำหรับเราในท้ายที่สุด (ฉันใช้ 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 การกระทำไม่ยกเลิกหรือยกเลิก")
Dariusz Wiechecki

คำตอบนี้มีความพิเศษตรงที่ให้วิธีปิดสแน็คบาร์ที่ตั้งค่าเป็น "LENGTH_INDEFINITE" (เพื่อให้ผู้ใช้มีเวลาอ่าน) โดยไม่ต้องเริ่มการทำงานใด ๆ เมื่อปุ่มการทำงานเริ่มทำงาน ฉันใช้แถบสแน็คบาร์เพื่อแจ้งให้ผู้เล่นทราบว่ามีการดาวน์โหลดอัปเดตแล้วและเริ่มต้นใหม่หากต้องการให้ใช้ หากพวกเขาไม่พร้อมที่จะรีสตาร์ทฉันต้องการวิธีปิดโดยไม่ต้องกดปุ่มดำเนินการ สแน็คบาร์บนอุปกรณ์ทดสอบของฉันไม่ได้ปิดด้วยการปัด รหัสนี้ปิดด้วยการ
สัมผัสนอก

3

แถบสแน็คบาร์ (จาก'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;

ปล. ในโค้ดตัวอย่างใช้นิพจน์แลมด้า (โดย RetroLambda)


คำถามไม่เกี่ยวกับตัวจัดการการเลิกจ้าง คำถามคือวิธีปิดเมื่อคลิกปุ่ม
เหลือเชื่อ

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


ไม่สมเหตุสมผลกับฉันเลย เหตุใดคุณจึงควรเรียก performClick () ถ้าคุณคลิกปุ่มจริงๆ ที่ดูเหมือนจะเป็นเรื่องไร้สาระ
เหลือเชื่อ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.