如何使用自己的操作按钮关闭 Snackbar?

How to dismiss a Snackbar using it's own Action button?

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 函数创建)关闭它。

然而,似乎没有任何可用的功能可以做到这一点。

对于Java,

.make 方法 returns 一个 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()

执行点击操作并让它清空。单击空的单击操作将关闭 snackbar 。

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

我遇到了同样的问题。当我使用 .dismiss() 时,动画看起来不一样并且有两个问题:

  1. FAB 没有再下降
  2. SnackBar 本身不会像单击时那样向下滑动

查看 Snackbar 的原始 Android 源代码,我找到了以下解决方案:

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

然后,我会在 snackBarActionButton 上调用 .performClick

snackBarActionButton.performClick();

Link 到 Snackbar 的 Android 源代码: https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/design/src/android/support/design/widget/Snackbar.java

Snackbar(来自'com.android.support:design:23.2.1')支持多种类型的关闭动作。您可以使用 event 创建一个简单的过滤器,例如在这个例子中:

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;

P.S。在示例代码中使用了 lambda 表达式(by RetroLambda)

当您使用 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

这是一个老问题,但我只是想分享我自己在 Snackbar 上类似功能的经验。所以我们为我们的应用程序设计了一个设计,应该无限期地显示 snackbar 并且用户应该能够关闭它..但是它里面不应该有 DISMISS 按钮(Google 不建议在 snackbars 中关闭或取消操作反正)。我们的小吃店必须通过点击它来关闭。

最终对我们有用的唯一解决方案(我在这里使用 retrolambda,但也可以使用标准 View.OnClickListener):

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

注意 getView() 在中间调用。

如果您想将 snackbar 放在静态方法中,请使用此方法。

 public static  void showSnackbar(Activity activity,String msg){
        Snackbar snackBar = null;

        snackBar = Snackbar.make( ((activity.findViewById(android.R.id.content))), msg,20000);//Snackbar.LENGTH_INDEFINITE
        Snackbar finalSnackBar = snackBar;
        //
        View.OnClickListener action =  new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                finalSnackBar.dismiss();
            }
        };

        snackBar.setAction("OKAY",action )
                .setActionTextColor(activity.getApplicationContext().getResources().getColor(android.R.color.holo_red_light ));
        snackBar.show();
    }