简体   繁体   中英

Why is my Android snackbar dismissed after clicking its action button?

I have a snackbar that I build with a duration set to Snackbar.LENGTH_INDEFINITE

The snackbar is displayed properly when I call mySnackbar.show();

But as soon as I hit the action button, the snackbar is dismissed.

The dismiss method seems called by the system.

Does anyone know a workaround ?

Here is my code for building my snackbar:

Snackbar mySnackbar = Snackbar.make(mParent, R.string.the_question, Snackbar.LENGTH_INDEFINITE)
                .setAction(R.string.yes, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                        //My code...
                    }
                })
                .addCallback(new Snackbar.Callback() {

                    @Override
                    public void onDismissed(Snackbar snackbar, int event) {
                    }

                    @Override
                    public void onShown(Snackbar snackbar) {
                    }
               });

Below code is showing the Alert dialog "after" the snackbar is displayed.

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content),
                "This is Snackbar", Snackbar.LENGTH_INDEFINITE).
                setAction(R.string.yes, new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {

                    }
                }).addCallback(new Snackbar.Callback() {

            @Override
            public void onDismissed(Snackbar transientBottomBar, int event) {
                super.onDismissed(transientBottomBar, event);

            }

            @Override
            public void onShown(Snackbar sb) {
                super.onShown(sb);

            }
        });
        snackbar.show();
        showAlertDialog(this, "Alert!!", "Alert Dialog", "Yes", "No");
    }

The showAlertDialog is simple static method to show the dialog

public static void showAlertDialog(Context context, String title, String message, String posBtnMsg, String negBtnMsg) {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle(title);
        builder.setMessage(message);
        builder.setPositiveButton(posBtnMsg, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        builder.setNegativeButton(negBtnMsg, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });
        AlertDialog dialog = builder.create();
        dialog.show();

    }

The screen shot of the output for above code is below,

在此处输入图片说明

The answer to this question lies in the way Snackbar.setAction(CharSequence text, final View.OnClickListener listener) is implemented

If you pass this method a non empty text or non null listener, the TextView displaying the action's text is set an OnClickListener which calls BaseTransientBottomBar.dispatchDismiss(BaseCallback.DISMISS_EVENT_ACTION) when the action is performed. This causes the Snackbar to be dismissed.

To prevent that, one needs to retrieve the TextView of the Snackbar's action view, and override its OnClickListener with a listener that does not call dispatchDismiss()

Here is the Snackbar.setAction() code for reference

public Snackbar setAction(CharSequence text, final View.OnClickListener listener) {

        final SnackbarContentLayout contentLayout = (SnackbarContentLayout) mView.getChildAt(0);
        final TextView tv = contentLayout.getActionView();

        if (TextUtils.isEmpty(text) || listener == null) {
            tv.setVisibility(View.GONE);
            tv.setOnClickListener(null);
        } else {
            tv.setVisibility(View.VISIBLE);
            tv.setText(text);
            tv.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    listener.onClick(view);
                    // Now dismiss the Snackbar
                    dispatchDismiss(BaseCallback.DISMISS_EVENT_ACTION);
                }
            });
        }
        return this;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM