diff options
4 files changed, 120 insertions, 30 deletions
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/LandscapeEdgeSwipeController.java index 92e9ac719..0605953dc 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 @@ public class LandscapeEdgeSwipeController extends AbstractStateChangeTouchContro @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 86deb43e0..40b030f62 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -69,6 +69,7 @@ public abstract class AbstractStateChangeTouchController protected final Launcher mLauncher; protected final SwipeDetector mDetector; + protected final SwipeDetector.Direction mSwipeDirection; private boolean mNoIntercept; protected int mStartContainerType; @@ -105,6 +106,7 @@ public abstract class AbstractStateChangeTouchController public AbstractStateChangeTouchController(Launcher l, SwipeDetector.Direction dir) { mLauncher = l; mDetector = new SwipeDetector(l, this, dir); + mSwipeDirection = dir; } protected long getAtomicDuration() { @@ -262,7 +264,8 @@ public abstract class AbstractStateChangeTouchController 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 a0a410e0d..e558fc7c7 100644 --- a/src/com/android/launcher3/touch/SwipeDetector.java +++ b/src/com/android/launcher3/touch/SwipeDetector.java @@ -24,6 +24,8 @@ import android.view.MotionEvent; 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 class SwipeDetector { 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 @@ public class SwipeDetector { } @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 @@ public class SwipeDetector { } @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 @@ public class SwipeDetector { 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 class SwipeDetector { } 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 @@ public class SwipeDetector { } // 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 @@ public class SwipeDetector { 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 @@ public class SwipeDetector { * @see #DIRECTION_BOTH */ public boolean wasInitialTouchPositive() { - return mSubtractDisplacement < 0; + return mDir.isPositive(mSubtractDisplacement); } private boolean reportDragging() { @@ -332,7 +373,7 @@ public class SwipeDetector { 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 b600473d4..4ebf54c7b 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.junit.runner.RunWith; 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 @@ public class SwipeDetectorTest { 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 @@ public class SwipeDetectorTest { } @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 @@ public class SwipeDetectorTest { } @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); |