OSDN Git Service

Fix PiP dismissing on drag away from bottom and then fling
authorMady Mellor <madym@google.com>
Wed, 22 Mar 2017 00:45:00 +0000 (17:45 -0700)
committerMady Mellor <madym@google.com>
Mon, 27 Mar 2017 17:07:49 +0000 (10:07 -0700)
Adds two flags to watch for movement outside of the starting area of the
gesture, one for dismissing and one for minimizing.

Test: - Have PiP at bottom of screen, drag to top and fling down (does not
        dismiss)
      - Have PiP at left or right edge of screen, drag PiP to opposite
        edge and fling to other side (no longer minimizes)
Bug: 35358628

Change-Id: I007e2c2c688254dbe1abaecdedc28e281278def8

packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java

index f70d5b4..b689a85 100644 (file)
@@ -104,6 +104,8 @@ public class PipTouchHandler {
     private int mImeHeight;
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
+    private boolean mMovementWithinMinimize;
+    private boolean mMovementWithinDismiss;
 
     // Touch state
     private final PipTouchState mTouchState;
@@ -435,6 +437,8 @@ public class PipTouchHandler {
      * Gesture controlling normal movement of the PIP.
      */
     private PipTouchGesture mDefaultMovementGesture = new PipTouchGesture() {
+        // Whether the PiP was on the left side of the screen at the start of the gesture
+        private boolean mStartedOnLeft;
 
         @Override
         public void onDown(PipTouchState touchState) {
@@ -442,6 +446,10 @@ public class PipTouchHandler {
                 return;
             }
 
+            mStartedOnLeft = mMotionHelper.getBounds().left < mMovementBounds.centerX();
+            mMovementWithinMinimize = true;
+            mMovementWithinDismiss = touchState.getDownTouchPosition().y >= mMovementBounds.bottom;
+
             // If the menu is still visible, and we aren't minimized, then just poke the menu
             // so that it will timeout after the user stops touching it
             if (mMenuController.isMenuVisible() && !mIsMinimized) {
@@ -493,6 +501,18 @@ public class PipTouchHandler {
                 if (ENABLE_DISMISS_DRAG_TO_EDGE) {
                     updateDismissFraction();
                 }
+
+                final PointF curPos = touchState.getLastTouchPosition();
+                if (mMovementWithinMinimize) {
+                    // Track if movement remains near starting edge to identify swipes to minimize
+                    mMovementWithinMinimize = mStartedOnLeft
+                            ? curPos.x <= mMovementBounds.left + mTmpBounds.width()
+                            : curPos.x >= mMovementBounds.right;
+                }
+                if (mMovementWithinDismiss) {
+                    // Track if movement remains near the bottom edge to identify swipe to dismiss
+                    mMovementWithinDismiss = curPos.y >= mMovementBounds.bottom;
+                }
                 return true;
             }
             return false;
@@ -526,8 +546,15 @@ public class PipTouchHandler {
             }
 
             if (touchState.isDragging()) {
+                final PointF vel = touchState.getVelocity();
+                final float velocity = PointF.length(vel.x, vel.y);
+                final boolean isFling = velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond();
+                final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
                 final boolean onLeft = mMotionHelper.getBounds().left < mMovementBounds.centerX();
-                boolean isFlingToBot = isFlingTowardsEdge(touchState, 4 /* bottom */);
+                final boolean isFlingToBot = !isHorizontal && mMovementWithinDismiss && vel.y > 0;
+                final boolean isFlingToEdge = isHorizontal && mMovementWithinMinimize
+                        && (onLeft ? vel.x < 0 : vel.x > 0);
+
                 if (ENABLE_DISMISS_DRAG_TO_EDGE
                         && (mMotionHelper.shouldDismissPip() || isFlingToBot)) {
                     mMotionHelper.animateDragToEdgeDismiss(mMotionHelper.getBounds(),
@@ -536,8 +563,7 @@ public class PipTouchHandler {
                             MetricsEvent.ACTION_PICTURE_IN_PICTURE_DISMISSED,
                             METRIC_VALUE_DISMISSED_BY_DRAG);
                     return true;
-                } else if (!mIsMinimized && (mMotionHelper.shouldMinimizePip()
-                        || isFlingTowardsEdge(touchState, onLeft ? 2 : 3))) {
+                } else if (!mIsMinimized && (mMotionHelper.shouldMinimizePip() || isFlingToEdge)) {
                     // Pip should be minimized
                     setMinimizedStateInternal(true);
                     if (mMenuController.isMenuVisible()) {
@@ -563,9 +589,7 @@ public class PipTouchHandler {
                     mMenuController.showMenu(mMotionHelper.getBounds(), mMovementBounds);
                 }
 
-                final PointF vel = mTouchState.getVelocity();
-                final float velocity = PointF.length(vel.x, vel.y);
-                if (velocity > mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+                if (isFling) {
                     mMotionHelper.flingToSnapTarget(velocity, vel.x, vel.y, mMovementBounds,
                             mUpdateScrimListener);
                 } else {
@@ -585,42 +609,6 @@ public class PipTouchHandler {
     };
 
     /**
-     * @return whether the gesture ending in {@param vel} is fast enough to be a fling and towards
-     *         the provided {@param edge} where:
-     *
-     *         1 = top
-     *         2 = left
-     *         3 = right
-     *         4 = bottom
-     */
-    private boolean isFlingTowardsEdge(PipTouchState touchState, int edge) {
-        final PointF vel = touchState.getVelocity();
-        final PointF downPos = touchState.getDownTouchPosition();
-        final Rect bounds = mMotionHelper.getBounds();
-        final boolean isHorizontal = Math.abs(vel.x) > Math.abs(vel.y);
-        final boolean isFling =
-                PointF.length(vel.x, vel.y) > mFlingAnimationUtils.getMinVelocityPxPerSecond();
-        if (!isFling) {
-            return false;
-        }
-        switch (edge) {
-            case 1: // top
-                return !isHorizontal && vel.y < 0
-                        && downPos.y <= mMovementBounds.top + bounds.height();
-            case 2: // left
-                return isHorizontal && vel.x < 0
-                        && downPos.x <= mMovementBounds.left + bounds.width();
-            case 3: // right
-                return isHorizontal && vel.x > 0
-                        && downPos.x >= mMovementBounds.right;
-            case 4: // bottom
-                return !isHorizontal && vel.y > 0
-                        && downPos.y >= mMovementBounds.bottom;
-        }
-        return false;
-    }
-
-    /**
      * Updates the current movement bounds based on whether the menu is currently visible.
      */
     private void updateMovementBounds(boolean isExpanded) {