3

I want to perform some tasks when user touch outside the dialog fragment. How can I do this?

  • In my custmom dialog fragment there's a piece of code to prevent dialog from closing when touch outside:

    getDialog().setCanceledOnTouchOutside(false);

huu duy
  • 2,049
  • 21
  • 31
  • @PierGiorgioMisley : I want to have a mechanism to handle any custom operation when user touch outside dialog not only for the dismissing. – huu duy Oct 04 '16 at 08:50

2 Answers2

2

Then you need to remove getDialog().setCanceledOnTouchOutside(false); and use some reflection to leverage Window's hidden method for deciding when to close dialog:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    return object : Dialog(activity as Context, theme) {
        override fun onTouchEvent(event: MotionEvent): Boolean {
            if (dialogShouldCloseOnTouch(window, context, event)) {
                // do custom logic
                return true
            } else {
                return super.onTouchEvent(event)
            }
        }
    }
}

private fun dialogShouldCloseOnTouch(
    window: Window, 
    context: Context, 
    event: MotionEvent): Boolean {
    val method = window.javaClass.getMethod("shouldCloseOnTouch", Context::class.java, MotionEvent::class.java)
    return method.invoke(window, context, event) as Boolean
}
DYS
  • 2,826
  • 2
  • 23
  • 34
  • @DYS, it doesn't work on some devices. Error: "Caused by: java.lang.NoSuchMethodException: com.android.internal.policy.PhoneWindow.shouldCloseOnTouch" – Gary Chen Dec 18 '20 at 09:26
  • @XueQing Could you tell me the Android version of such devices? – DYS Dec 24 '20 at 03:59
  • @DYS, Your code is working well on emulator. But I couldn't use the logic because of the such error. My phone has android 10 version. – Gary Chen Dec 24 '20 at 05:08
  • 1
    @XueQing It could be. In this case you could simply try copy-pasting `Window.shouldCloseOnTouch` to your `Fragment`. – DYS Jan 04 '21 at 09:10
0
public class MyActivity extends Activity {

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

    // Make us non-modal, so that others can receive touch events.
    getWindow().setFlags(LayoutParams.FLAG_NOT_TOUCH_MODAL, LayoutParams.FLAG_NOT_TOUCH_MODAL);

    // ...but notify us that it happened.
    getWindow().setFlags(LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);

    // Note that flag changes must happen *before* the content view is set.
    setContentView(R.layout.my_dialog_view);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    // If we've received a touch notification that the user has touched
    // outside the app, finish the activity.
    if (MotionEvent.ACTION_OUTSIDE == event.getAction()) {
      //outside touch event
      return true;
    }

    // Delegate everything else to Activity.
    return super.onTouchEvent(event);
  }
}

Reference: Look at the second answer here.

P.S. In the question he said he has an activity with the dialog theme.

Community
  • 1
  • 1
Aman Grover
  • 1,621
  • 1
  • 21
  • 41