From 45385e2ac3ee7b723fe14f10becd169f175bb419 Mon Sep 17 00:00:00 2001 From: Siarhei Vishniakou Date: Wed, 15 May 2019 10:50:09 -0700 Subject: Close windows on ACTION_UP when touched outside If a window is touched inside the touchable region, but outside of the physical frame, the setting closeOnTouchOutside=True for this window would mean that the window would close. Currently, the window would close when ACTION_DOWN on the touchable region happens. However, with the new gesture nav, the KEYCODE_BACK would also be injected. Normally, the KEYCODE_BACK would also close the window. But if the window is already closed in response to ACTION_DOWN, the KEYCODE_BACK event would cause the underlying window to close. This could be confusing to the user, because in this case a single action (swiping back outside of the dialog) causes 2 actions to occur: the dismissal of the window, and the navigation back to the previous screen of the underlying window. To avoid this poor user experience, we instead dismiss the window when ACTION_UP inside the touchable area happens. UX impact: This CL would not change the user experience for tapping to dismiss the dialogs, because tap has a short duration between down and up (most common usecase). This CL would now allow the user to maintain the finger on the screen outside of the dialog for an arbitrary amount of time, without the dialog disappearing. When the finger is lifted, the dialog would be dismissed. This CL improves the user experience for gesturing back to dismiss the dialog, because the dialog most of the time will dismiss and nothing else will happen. However, there still exists opportunity to cause the old behaviour. The window can receive ACTION_UP before KEYCODE_BACK is injected by gesture nav. Important! If BACK is received by the app after ACTION_UP is received (can happen occasionally), then the we would still see 2 actions happen in response to a single swipe. This issue is tracked in b/132735993, but it is likely that it will remain in Q. Bug: 131410670 Test: open any dialog (for example, go to settings->display->screen timeout), then press outside of the dialog and hold. Watch that the window is not dismissed. Then release finger. Watch that the dialog dismisses. Also, gesture back outside of the dialog area. Watch that the dialog disappears and nothing else happens (but see the important note above for exceptions to this). Change-Id: I2e7c1bab986f019dc2f4640ff9f4151ebb96479c --- core/java/android/view/Window.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core/java/android/view/Window.java') diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java index cbcc057811fd..c16b8e02c807 100644 --- a/core/java/android/view/Window.java +++ b/core/java/android/view/Window.java @@ -1300,7 +1300,7 @@ public abstract class Window { @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public boolean shouldCloseOnTouch(Context context, MotionEvent event) { final boolean isOutside = - event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event) + event.getAction() == MotionEvent.ACTION_UP && isOutOfBounds(context, event) || event.getAction() == MotionEvent.ACTION_OUTSIDE; if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) { return true; -- cgit v1.2.3