From 945bb34b5efbd78a9701f431da1a5b866e0a3d90 Mon Sep 17 00:00:00 2001 From: Bill Lin Date: Thu, 3 Jun 2021 01:29:39 +0800 Subject: [PATCH 1/2] 1/ Provides feasibility to adjust touch slop in TouchController There is a case when one handed mode triggered(Activated), all apps drawer is very easy to trigger while user swipe up around NavBar region to exit one handed mode. Since System Gesture monitor regsion is small on screen bottom, swipe-up gesture usually cross over NavBar monitor region and invoke launcher touch controller intercept touch event and introduce unexpectedly trigger all apps drawer. Adding onOneHandedModeStateChanged(boolean activated) for controller be able to adjust the touch slop by multiplier, we can set a larger multiplier when the visible window size translate become smaller and make swipe gesture not too sensitive. Test: manual swipe up to swich "home <-> all apps" and monitor minDisplacement of SingleAxisSwipeDetector Test: Trigger one handed mode and swipe up to exit one handed mode check the minDisplacement of SingleAxisSwipeDetector Bug: 186235522 Change-Id: I9729cd408d85b2b22582bf800e28d1471fc06980 --- ...NoButtonNavbarToOverviewTouchController.java | 12 +++++++++++- .../android/launcher3/dragndrop/DragLayer.java | 11 +++++++++++ .../touch/SingleAxisSwipeDetector.java | 17 ++++++++++++++++- .../android/launcher3/util/TouchController.java | 5 +++++ 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index eb62110065..283743dc64 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -51,7 +51,7 @@ import com.android.quickstep.views.RecentsView; * first home screen instead of to Overview. */ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouchController { - + private static final float ONE_HANDED_ACTIVATED_SLOP_MULTIPLIER = 2.5f; // How much of the movement to use for translating overview after swipe and hold. private static final float OVERVIEW_MOVEMENT_FACTOR = 0.25f; @@ -260,4 +260,14 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch private float dpiFromPx(float pixels) { return Utilities.dpiFromPx(pixels, mLauncher.getResources().getDisplayMetrics().densityDpi); } + + @Override + public void onOneHandedModeStateChanged(boolean activated) { + if (activated) { + mDetector.setTouchSlopMultiplier(ONE_HANDED_ACTIVATED_SLOP_MULTIPLIER); + } else { + // Reset touch slop multiplier to default 1.0f + mDetector.setTouchSlopMultiplier(1f /* default */); + } + } } diff --git a/src/com/android/launcher3/dragndrop/DragLayer.java b/src/com/android/launcher3/dragndrop/DragLayer.java index c2f609c6a7..011325d6cf 100644 --- a/src/com/android/launcher3/dragndrop/DragLayer.java +++ b/src/com/android/launcher3/dragndrop/DragLayer.java @@ -48,6 +48,7 @@ import com.android.launcher3.folder.Folder; import com.android.launcher3.graphics.Scrim; import com.android.launcher3.keyboard.ViewGroupFocusHelper; import com.android.launcher3.util.Thunk; +import com.android.launcher3.util.TouchController; import com.android.launcher3.views.BaseDragLayer; import java.util.ArrayList; @@ -519,4 +520,14 @@ public class DragLayer extends BaseDragLayer { public Scrim getWorkspaceDragScrim() { return mWorkspaceDragScrim; } + + /** + * Called when one handed mode state changed. + * @param activated true if one handed mode activated, false otherwise. + */ + public void onOneHandedModeStateChanged(boolean activated) { + for (TouchController controller : mControllers) { + controller.onOneHandedModeStateChanged(activated); + } + } } diff --git a/src/com/android/launcher3/touch/SingleAxisSwipeDetector.java b/src/com/android/launcher3/touch/SingleAxisSwipeDetector.java index 8c3c115334..f751b7d505 100644 --- a/src/com/android/launcher3/touch/SingleAxisSwipeDetector.java +++ b/src/com/android/launcher3/touch/SingleAxisSwipeDetector.java @@ -102,6 +102,8 @@ public class SingleAxisSwipeDetector extends BaseSwipeDetector { private int mScrollDirections; + private float mTouchSlopMultiplier = 1f; + public SingleAxisSwipeDetector(@NonNull Context context, @NonNull Listener l, @NonNull Direction dir) { this(ViewConfiguration.get(context), l, dir, Utilities.isRtl(context.getResources())); @@ -115,6 +117,19 @@ public class SingleAxisSwipeDetector extends BaseSwipeDetector { mDir = dir; } + /** + * Provides feasibility to adjust touch slop when visible window size changed. When visible + * bounds translate become smaller, multiply a larger multiplier could ensure the UX + * more consistent. + * + * @see #shouldScrollStart(PointF) + * + * @param touchSlopMultiplier the value to multiply original touch slop. + */ + public void setTouchSlopMultiplier(float touchSlopMultiplier) { + mTouchSlopMultiplier = touchSlopMultiplier; + } + public void setDetectableScrollConditions(int scrollDirectionFlags, boolean ignoreSlop) { mScrollDirections = scrollDirectionFlags; mIgnoreSlopWhenSettling = ignoreSlop; @@ -133,7 +148,7 @@ public class SingleAxisSwipeDetector extends BaseSwipeDetector { @Override protected boolean shouldScrollStart(PointF displacement) { // Reject cases where the angle or slop condition is not met. - float minDisplacement = Math.max(mTouchSlop, + float minDisplacement = Math.max(mTouchSlop * mTouchSlopMultiplier, Math.abs(mDir.extractOrthogonalDirection(displacement))); if (Math.abs(mDir.extractDirection(displacement)) < minDisplacement) { return false; diff --git a/src/com/android/launcher3/util/TouchController.java b/src/com/android/launcher3/util/TouchController.java index fc1d819f78..9c397c0f74 100644 --- a/src/com/android/launcher3/util/TouchController.java +++ b/src/com/android/launcher3/util/TouchController.java @@ -32,5 +32,10 @@ public interface TouchController { */ boolean onControllerInterceptTouchEvent(MotionEvent ev); + /** + * Called when one handed mode state changed + */ + default void onOneHandedModeStateChanged(boolean activated) { } + default void dump(String prefix, PrintWriter writer) { } } From a1221bcd534f3aecc44fac52b2999d316b0c472c Mon Sep 17 00:00:00 2001 From: Bill Lin Date: Thu, 3 Jun 2021 01:49:27 +0800 Subject: [PATCH 2/2] 2/ Notify adjust touch slop when one handed mode activated When one handed mode activated, user swipe-up to exit usually cross over the NavBar region, and then invoke TouchController intercept touch event to trigger All Apps drawer on Home. To enhanced the UX of gesture conflict of exit OHM & All Apps, notify TouchController throught LauncherActivityInterface, and Launcher dispatch onOneHandedModeStateChanged() event to all mTouchControllers in DragLayer that touchController can adjust the touch slop by it's SingleAxisSwipeDetector. Test: manual trigger One handed mode and swipe-up to exit Test: monitor minDisplacement of SingleAxisSwipeDetector OHM activated : touchSlop x multiplier OHM deactivated : touchSlop x 1 Test: check All Apps doesn't mis-trigger when exit one handed mode Bug: 186235522 Change-Id: I7b9e6e7fa898231697d1866186a5f9b1717a9aa3 --- .../src/com/android/quickstep/BaseActivityInterface.java | 3 +++ .../com/android/quickstep/FallbackActivityInterface.java | 5 +++++ .../com/android/quickstep/LauncherActivityInterface.java | 9 +++++++++ .../com/android/quickstep/OverviewComponentObserver.java | 5 +++++ src/com/android/launcher3/Launcher.java | 8 ++++++++ 5 files changed, 30 insertions(+) diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 4ae6fa8541..7ab371b4d9 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -114,6 +114,9 @@ public abstract class BaseActivityInterface callback); diff --git a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java index 4ee4398d81..906599f560 100644 --- a/quickstep/src/com/android/quickstep/FallbackActivityInterface.java +++ b/quickstep/src/com/android/quickstep/FallbackActivityInterface.java @@ -73,6 +73,11 @@ public final class FallbackActivityInterface extends // set to zero prior to this class becoming active. } + @Override + public void onOneHandedModeStateChanged(boolean activated) { + // Do nothing for FallbackActivityInterface + } + /** 6 */ @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java index 9014774ae7..30abfbb922 100644 --- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java +++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java @@ -104,6 +104,15 @@ public final class LauncherActivityInterface extends launcher.onAssistantVisibilityChanged(visibility); } + @Override + public void onOneHandedModeStateChanged(boolean activated) { + Launcher launcher = getCreatedActivity(); + if (launcher == null) { + return; + } + launcher.onOneHandedStateChanged(activated); + } + @Override public AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState, boolean activityVisible, Consumer callback) { diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java index fb8f9fe31d..0efe6666a8 100644 --- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java +++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java @@ -111,6 +111,11 @@ public final class OverviewComponentObserver { if (mDeviceState.isHomeDisabled() != mIsHomeDisabled) { updateOverviewTargets(); } + + // Notify ALL_APPS touch controller when one handed mode state activated or deactivated + if (mDeviceState.isOneHandedModeEnabled()) { + mActivityInterface.onOneHandedModeStateChanged(mDeviceState.isOneHandedModeActive()); + } } private void updateOverviewTargets(Intent unused) { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 8889e60688..299c68fdb5 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -576,6 +576,14 @@ public class Launcher extends StatefulActivity implements Launche mHotseat.getQsb().setAlpha(1f - visibility); } + /** + * Called when one handed mode activated and deactivated. + * @param activated true if one handed mode activated, false otherwise. + */ + public void onOneHandedStateChanged(boolean activated) { + mDragLayer.onOneHandedModeStateChanged(activated); + } + private void initDeviceProfile(InvariantDeviceProfile idp) { // Load configuration-specific DeviceProfile mDeviceProfile = idp.getDeviceProfile(this);