Allow outside touch for DialogFragment

北战南征 提交于 2019-11-26 22:26:20

问题


I have a Fragment in my app that shows a DialogFragment.
I have in the fragment a button that closes the dialog. But when I show the dialogFragment, the touches outside from the dialog do nothing and I can't click the buttons outside from the dialog fragment.

How can I allow outside touches for DialogFragment?


回答1:


In order to do that, a flag of the Window that allows the outside touch should be turned on and for the good appearance the background dim flag should be cleared.
Since it must be done after dialog is created, I've implemented it via the Handler.

@Override
public void onViewCreated(final View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    // This is done in a post() since the dialog must be drawn before locating.
    getView().post(new Runnable() {

        @Override
        public void run() {

            Window dialogWindow = getDialog().getWindow();

            // Make the dialog possible to be outside touch
            dialogWindow.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL,
                    WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
            dialogWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);

            getView().invalidate();
        }
    });
}

At this moment the outside touch is possible.

In case we want to make it nicer and without the frame, the following code can be added:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Hide title of the dialog
    setStyle(STYLE_NO_FRAME, 0);
}



回答2:


This is more generic flag to allow any action not only touch actions

window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
        WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);



回答3:


I have found alternative way to handle dismiss on touch outside. Please check below code sample, that would definitely work,

@Override
public void onStart() {
    // mDialogView is member variable
    mDialogView = getView();
    mDialogView.setOnTouchListener(new View.OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            float eventX = event.getRawX();
            float eventY = event.getRawY();

            int location[] = new int[2];
            mDialogView.getLocationOnScreen(location);

            if (eventX < location[0] || eventX > (location[0] + mDialogView.getWidth()) || eventY < location[1]
                    || eventY > location[1] + mDialogView.getHeight()) {
                dismiss();
                return true;
            }
            return false;
        }
    });
}

In my case, I was getting getDialog() as not null value, but getDialog().dismiss() was not working. Also, the solution that is marked as right above, also did not work in my case. So, I took this approach.




回答4:


You need to set a proper style for your needs. You can read more about styles for FragmentDialogs in the official docs.

I believe you could use following style:

  • STYLE_NO_FRAME



回答5:


Well, let's be specific. If you want to work with outside views then you should not use dialog fragment, use fragment instead like this.

 FragmentTransaction transaction = fragmentManager.beginTransaction();
    // For a little polish, specify a transition animation
    transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    // To make it fullscreen, use the 'content' root view as the container
    // for the fragment, which is always the root view for the activity
    transaction.add(android.R.id.content, newFragment)
               .addToBackStack(null).commit();

And make the layout wrap_content, which will apparently looks like Dialog and by default it is placed at the top of the screen.

For more details please visit here




回答6:


@yaniv has provided the answer. But in case you want, here's a snippet where you get the same result but withou the need to post a Runnable to the root View:

@NonNull
@Override
public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) {
    final Dialog dialog = super.onCreateDialog(savedInstanceState);
    dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
    return dialog;
}


来源:https://stackoverflow.com/questions/15382540/allow-outside-touch-for-dialogfragment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!