BottomSheetDialogFragment - 听取用户事件解雇

时间:2016-11-15 18:11:25

标签: android dialog android-dialogfragment dialogfragment bottom-sheet

我如何听取BottomSheetDialogFragment的最终解雇?我想仅在最终解雇时保存用户更改...

我试过以下:

方法1

如果通过向下滑动对话框解除对话(不在背面按压或外面触摸),则仅触发此消息

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    Dialog d = super.onCreateDialog(savedInstanceState);
    d.setOnShowListener(new DialogInterface.OnShowListener() {
        @Override
        public void onShow(DialogInterface dialog) {

            BottomSheetDialog d = (BottomSheetDialog) dialog;   
            FrameLayout bottomSheet = (FrameLayout) dialog.findViewById(android.support.design.R.id.design_bottom_sheet);

            BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
            behaviour.setState(BottomSheetBehavior.STATE_EXPANDED);
            behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                @Override
                public void onStateChanged(@NonNull View bottomSheet, int newState) {
                    if (newState == BottomSheetBehavior.STATE_HIDDEN)
                    {
                        // Bottom Sheet was dismissed by user! But this is only fired, if dialog is swiped down! Not if touch outside dismissed the dialog or the back button
                        Toast.makeText(MainApp.get(), "HIDDEN", Toast.LENGTH_SHORT).show();
                        dismiss();
                    }
                }

                @Override
                public void onSlide(@NonNull View bottomSheet, float slideOffset) {

                }
            });
        }
    });
    return d;
}

方法2

这不允许我区分最终解雇和来自屏幕轮换或活动娱乐的解雇......

 @Override
public void onDismiss(DialogInterface dialog)
{
    super.onDismiss(dialog);
    // this works fine but fires one time too often for my use case, it fires on screen rotation as well, although this is a temporarily dismiss only
    Toast.makeText(MainApp.get(), "DISMISSED", Toast.LENGTH_SHORT).show();
}

问题

如何收听指示用户已完成对话的事件?

6 个答案:

答案 0 :(得分:31)

虽然关于SO的所有类似问题建议使用onDismiss我认为以下是正确的解决方案:

@Override
public void onCancel(DialogInterface dialog)
{
    super.onCancel(dialog);
    Toast.makeText(MainApp.get(), "CANCEL", Toast.LENGTH_SHORT).show();
}

如果出现以下情况,则会触发:

* the user presses back
* the user presses outside of the dialog

这不会引发:

* on screen rotation and activity recreation

<强>解决方案

onCancel BottomSheetBehavior.BottomSheetCallback.onStateChanged 合并如下:

public class Dailog extends BottomSheetDialogFragment
{
    @Override
    public void onCancel(DialogInterface dialog)
    {
        super.onCancel(dialog);
        handleUserExit();
    }

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
        Dialog d = super.onCreateDialog(savedInstanceState);
        d.setOnShowListener(new DialogInterface.OnShowListener() {
            @Override
            public void onShow(DialogInterface dialog) {
                BottomSheetDialog d = (BottomSheetDialog) dialog;
                FrameLayout bottomSheet = (FrameLayout) d.findViewById(android.support.design.R.id.design_bottom_sheet);
                BottomSheetBehavior behaviour = BottomSheetBehavior.from(bottomSheet);
                behaviour.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
                    @Override
                    public void onStateChanged(@NonNull View bottomSheet, int newState) {
                        if (newState == BottomSheetBehavior.STATE_HIDDEN)
                        {
                            handleUserExit();
                            dismiss();
                        }
                    }

                    @Override
                    public void onSlide(@NonNull View bottomSheet, float slideOffset) {

                    }
                });
            }
        });
        return d;
    }

    private void handleUserExit()
    {
        Toast.makeText(MainApp.get(), "TODO - SAVE data or similar", Toast.LENGTH_SHORT).show();
    }
}

答案 1 :(得分:2)

如果您是从BottomSheetDialogFragment()扩展而来的,请在您的课程中覆盖

 override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        //Code here
    }

这将在 onBackPress 以及您通过单击对话框的外部将其关闭而触发。

请确保不要将对话框设置为可取消,因为这不会触发

答案 2 :(得分:1)

我通过这个简单的技巧实现了这一目标

val bottomSheetDialog = FeedbackFormsFragment.createInstance()
bottomSheetDialog.show((activity as FragmentActivity).supportFragmentManager, BOTTOM_SHEET)


// add some delay to allow the bottom sheet to be visible first so that the dialog is not null

                Handler().postDelayed({
                    bottomSheetDialog.dialog?.setOnDismissListener {

                       // add code here
                    }
                }, 1000)

答案 3 :(得分:1)

bottomSheetDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
   @Override
   public void onDismiss(DialogInterface dialog) {
       toast("dismissed");
   }
});

答案 4 :(得分:0)

虽然@ prom85的方法有效,但是有另一种方法。如果您想在一种情况下关闭BottomSheetDialogFragment而在另一种情况下保留,则该方法将无效。在所有情况下都将关闭对话框。

例如,如果您在EditText的{​​{1}}内输入文本,并偶尔在外部单击,它将关闭对话框而没有任何警告。我尝试了https://medium.com/@anitas3791/android-bottomsheetdialog-3871a6e9d538,它可以工作,但是在另一种情况下。向下拖动对话框时,它将关闭。如果您在外部单击,它将不会显示任何警报消息,也不会关闭该对话框。

因此,我使用了https://stackoverflow.com/a/50734566/2914140的@shijo很好的建议。

将这些行添加到BottomSheetDialogFragment方法(或onActivityCreated之后的任何其他生命周期方法)。

onCreateView

@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); View touchOutsideView = getDialog().getWindow() .getDecorView() .findViewById(android.support.design.R.id.touch_outside); touchOutsideView.setOnClickListener(yourClickListener); } 中,我检查文本并显示警报或关闭对话框:

yourClickListener

创建private fun checkAndDismiss() { if (newText == oldText) { dismissAllowingStateLoss() } else { showDismissAlert() } } 时,请勿像https://stackoverflow.com/a/42679131/2914140那样调用BottomSheetDialogFragment,否则这些方法可能行不通。也许不要在样式中设置setCancelable(false)或在<item name="android:windowCloseOnTouchOutside">false</item>中设置setCanceledOnTouchOutside(false)


我还尝试了几种方法来取消取消行为,但没有成功。

onCreateDialog

答案 5 :(得分:0)

PRIVATE中,您可以使用以下技术:

libA-objs

请务必在致电工作表上的AppCompatActivity之前执行上述操作。