Fix SwipeDetector positive vs negative for HORIZONTAL direction
Previously left was considered positive and right considered negative.
Now left and down are negative, and right and up are positive.
For RTL, left is positive and right is negative.
Change-Id: Ia31e8c687c8c2716fc632b2fe88aa8955b934bce
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
index 92e9ac7..0605953 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java
@@ -41,7 +41,7 @@
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
- boolean draggingFromNav = mLauncher.getDeviceProfile().isSeascape() != isDragTowardPositive;
+ boolean draggingFromNav = mLauncher.getDeviceProfile().isSeascape() == isDragTowardPositive;
return draggingFromNav ? OVERVIEW : NORMAL;
}
diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
index 86deb43..40b030f 100644
--- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
+++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java
@@ -69,6 +69,7 @@
protected final Launcher mLauncher;
protected final SwipeDetector mDetector;
+ protected final SwipeDetector.Direction mSwipeDirection;
private boolean mNoIntercept;
protected int mStartContainerType;
@@ -105,6 +106,7 @@
public AbstractStateChangeTouchController(Launcher l, SwipeDetector.Direction dir) {
mLauncher = l;
mDetector = new SwipeDetector(l, this, dir);
+ mSwipeDirection = dir;
}
protected long getAtomicDuration() {
@@ -262,7 +264,8 @@
float deltaProgress = mProgressMultiplier * (displacement - mDisplacementShift);
float progress = deltaProgress + mStartProgress;
updateProgress(progress);
- boolean isDragTowardPositive = (displacement - mDisplacementShift) < 0;
+ boolean isDragTowardPositive = mSwipeDirection.isPositive(
+ displacement - mDisplacementShift);
if (progress <= 0) {
if (reinitCurrentAnimation(false, isDragTowardPositive)) {
mDisplacementShift = displacement;
diff --git a/src/com/android/launcher3/touch/SwipeDetector.java b/src/com/android/launcher3/touch/SwipeDetector.java
index a0a410e..e558fc7 100644
--- a/src/com/android/launcher3/touch/SwipeDetector.java
+++ b/src/com/android/launcher3/touch/SwipeDetector.java
@@ -24,6 +24,8 @@
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
+import com.android.launcher3.Utilities;
+
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -64,20 +66,25 @@
public static abstract class Direction {
- abstract float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint);
+ abstract float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint,
+ boolean isRtl);
/**
* Distance in pixels a touch can wander before we think the user is scrolling.
*/
abstract float getActiveTouchSlop(MotionEvent ev, int pointerIndex, PointF downPos);
- abstract float getVelocity(VelocityTracker tracker);
+ abstract float getVelocity(VelocityTracker tracker, boolean isRtl);
+
+ abstract boolean isPositive(float displacement);
+
+ abstract boolean isNegative(float displacement);
}
public static final Direction VERTICAL = new Direction() {
@Override
- float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint) {
+ float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint, boolean isRtl) {
return ev.getY(pointerIndex) - refPoint.y;
}
@@ -87,16 +94,32 @@
}
@Override
- float getVelocity(VelocityTracker tracker) {
+ float getVelocity(VelocityTracker tracker, boolean isRtl) {
return tracker.getYVelocity();
}
+
+ @Override
+ boolean isPositive(float displacement) {
+ // Up
+ return displacement < 0;
+ }
+
+ @Override
+ boolean isNegative(float displacement) {
+ // Down
+ return displacement > 0;
+ }
};
public static final Direction HORIZONTAL = new Direction() {
@Override
- float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint) {
- return ev.getX(pointerIndex) - refPoint.x;
+ float getDisplacement(MotionEvent ev, int pointerIndex, PointF refPoint, boolean isRtl) {
+ float displacement = ev.getX(pointerIndex) - refPoint.x;
+ if (isRtl) {
+ displacement = -displacement;
+ }
+ return displacement;
}
@Override
@@ -105,8 +128,24 @@
}
@Override
- float getVelocity(VelocityTracker tracker) {
- return tracker.getXVelocity();
+ float getVelocity(VelocityTracker tracker, boolean isRtl) {
+ float velocity = tracker.getXVelocity();
+ if (isRtl) {
+ velocity = -velocity;
+ }
+ return velocity;
+ }
+
+ @Override
+ boolean isPositive(float displacement) {
+ // Right
+ return displacement > 0;
+ }
+
+ @Override
+ boolean isNegative(float displacement) {
+ // Left
+ return displacement < 0;
}
};
@@ -159,6 +198,7 @@
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
private final Direction mDir;
+ private final boolean mIsRtl;
private final float mTouchSlop;
private final float mMaxVelocity;
@@ -183,14 +223,15 @@
}
public SwipeDetector(@NonNull Context context, @NonNull Listener l, @NonNull Direction dir) {
- this(ViewConfiguration.get(context), l, dir);
+ this(ViewConfiguration.get(context), l, dir, Utilities.isRtl(context.getResources()));
}
@VisibleForTesting
protected SwipeDetector(@NonNull ViewConfiguration config, @NonNull Listener l,
- @NonNull Direction dir) {
+ @NonNull Direction dir, boolean isRtl) {
mListener = l;
mDir = dir;
+ mIsRtl = isRtl;
mTouchSlop = config.getScaledTouchSlop();
mMaxVelocity = config.getScaledMaximumFlingVelocity();
}
@@ -212,8 +253,8 @@
}
// Check if the client is interested in scroll in current direction.
- if (((mScrollConditions & DIRECTION_NEGATIVE) > 0 && mDisplacement > 0) ||
- ((mScrollConditions & DIRECTION_POSITIVE) > 0 && mDisplacement < 0)) {
+ if (((mScrollConditions & DIRECTION_NEGATIVE) > 0 && mDir.isNegative(mDisplacement)) ||
+ ((mScrollConditions & DIRECTION_POSITIVE) > 0 && mDir.isPositive(mDisplacement))) {
return true;
}
return false;
@@ -259,7 +300,7 @@
if (pointerIndex == INVALID_POINTER_ID) {
break;
}
- mDisplacement = mDir.getDisplacement(ev, pointerIndex, mDownPos);
+ mDisplacement = mDir.getDisplacement(ev, pointerIndex, mDownPos, mIsRtl);
// handle state and listener calls.
if (mState != ScrollState.DRAGGING && shouldScrollStart(ev, pointerIndex)) {
@@ -315,7 +356,7 @@
* @see #DIRECTION_BOTH
*/
public boolean wasInitialTouchPositive() {
- return mSubtractDisplacement < 0;
+ return mDir.isPositive(mSubtractDisplacement);
}
private boolean reportDragging() {
@@ -332,7 +373,7 @@
private void reportDragEnd() {
mVelocityTracker.computeCurrentVelocity(1000, mMaxVelocity);
- float velocity = mDir.getVelocity(mVelocityTracker) / 1000;
+ float velocity = mDir.getVelocity(mVelocityTracker, mIsRtl) / 1000;
if (DBG) {
Log.d(TAG, String.format("onScrollEnd disp=%.1f, velocity=%.1f",
mDisplacement, velocity));
diff --git a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
index b600473..4ebf54c 100644
--- a/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
+++ b/tests/src/com/android/launcher3/touch/SwipeDetectorTest.java
@@ -15,9 +15,12 @@
*/
package com.android.launcher3.touch;
-import androidx.test.InstrumentationRegistry;
-import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
+import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
import android.util.Log;
import android.view.ViewConfiguration;
@@ -29,11 +32,9 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.anyFloat;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
@SmallTest
@RunWith(AndroidJUnit4.class)
@@ -63,7 +64,7 @@
doReturn(orgConfig.getScaledMaximumFlingVelocity()).when(mMockConfig)
.getScaledMaximumFlingVelocity();
- mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.VERTICAL);
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.VERTICAL, false);
mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_BOTH, false);
mTouchSlop = orgConfig.getScaledTouchSlop();
doReturn(mTouchSlop).when(mMockConfig).getScaledTouchSlop();
@@ -72,7 +73,19 @@
}
@Test
- public void testDragStart_vertical() {
+ public void testDragStart_verticalPositive() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.VERTICAL, false);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
+ mGenerator.put(0, 100, 100);
+ mGenerator.move(0, 100, 100 - mTouchSlop);
+ // TODO: actually calculate the following parameters and do exact value checks.
+ verify(mMockListener).onDragStart(anyBoolean());
+ }
+
+ @Test
+ public void testDragStart_verticalNegative() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.VERTICAL, false);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_NEGATIVE, false);
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100, 100 + mTouchSlop);
// TODO: actually calculate the following parameters and do exact value checks.
@@ -88,9 +101,42 @@
}
@Test
- public void testDragStart_horizontal() {
- mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL);
- mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_BOTH, false);
+ public void testDragStart_horizontalPositive() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL, false);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
+
+ mGenerator.put(0, 100, 100);
+ mGenerator.move(0, 100 + mTouchSlop, 100);
+ // TODO: actually calculate the following parameters and do exact value checks.
+ verify(mMockListener).onDragStart(anyBoolean());
+ }
+
+ @Test
+ public void testDragStart_horizontalNegative() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL, false);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_NEGATIVE, false);
+
+ mGenerator.put(0, 100, 100);
+ mGenerator.move(0, 100 - mTouchSlop, 100);
+ // TODO: actually calculate the following parameters and do exact value checks.
+ verify(mMockListener).onDragStart(anyBoolean());
+ }
+
+ @Test
+ public void testDragStart_horizontalRtlPositive() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL, true);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_POSITIVE, false);
+
+ mGenerator.put(0, 100, 100);
+ mGenerator.move(0, 100 - mTouchSlop, 100);
+ // TODO: actually calculate the following parameters and do exact value checks.
+ verify(mMockListener).onDragStart(anyBoolean());
+ }
+
+ @Test
+ public void testDragStart_horizontalRtlNegative() {
+ mDetector = new SwipeDetector(mMockConfig, mMockListener, SwipeDetector.HORIZONTAL, true);
+ mDetector.setDetectableScrollConditions(SwipeDetector.DIRECTION_NEGATIVE, false);
mGenerator.put(0, 100, 100);
mGenerator.move(0, 100 + mTouchSlop, 100);