Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 352b978f authored by Adam Powell's avatar Adam Powell
Browse files

Fix some bugs/edge cases in ScrollView/HorizontalScrollView

Handle ACTION_CANCEL, fix edge cases related to grabbing content and
beginning a new scroll during overfling/springback. Will prevent
some cases where a view could get stuck overscrolled.

Change-Id: I7e89d9de9b7dc685d2ea278e6b2bd2c794364204
parent 3e8b72ac
Loading
Loading
Loading
Loading
+28 −10
Original line number Diff line number Diff line
@@ -372,11 +372,12 @@ public class HorizontalScrollView extends FrameLayout {

    private boolean inChild(int x, int y) {
        if (getChildCount() > 0) {
            final int scrollX = mScrollX;
            final View child = getChildAt(0);
            return !(y < child.getTop()
                    || y >= child.getBottom()
                    || x < child.getLeft()
                    || x >= child.getRight());
                    || x < child.getLeft() - scrollX
                    || x >= child.getRight() - scrollX);
        }
        return false;
    }
@@ -455,6 +456,9 @@ public class HorizontalScrollView extends FrameLayout {
                /* Release the drag */
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                if (mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) {
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
@@ -486,6 +490,11 @@ public class HorizontalScrollView extends FrameLayout {

        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float x = ev.getX();
                if (!(mIsBeingDragged = inChild((int) x, (int) ev.getY()))) {
                    return false;
                }

                /*
                 * If being flinged and user touches, stop the fling. isFinished
                 * will be false if being flinged.
@@ -494,13 +503,9 @@ public class HorizontalScrollView extends FrameLayout {
                    mScroller.abortAnimation();
                }

                final float x = ev.getX();
                if (!(mIsBeingDragged = inChild((int) x, (int) ev.getY()))) {
                    return false;
                }

                // Remember where the motion event started
                mLastMotionX = x;
                mActivePointerId = ev.getPointerId(0);
                break;
            }
            case MotionEvent.ACTION_MOVE:
@@ -544,6 +549,19 @@ public class HorizontalScrollView extends FrameLayout {
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                if (mIsBeingDragged && getChildCount() > 0) {
                    if (mScroller.springback(mScrollX, mScrollY, 0, getScrollRange(), 0, 0)) {
                        invalidate();
                    }
                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;
                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
+27 −10
Original line number Diff line number Diff line
@@ -370,9 +370,10 @@ public class ScrollView extends FrameLayout {

    private boolean inChild(int x, int y) {
        if (getChildCount() > 0) {
            final int scrollY = mScrollY;
            final View child = getChildAt(0);
            return !(y < child.getTop()
                    || y >= child.getBottom()
            return !(y < child.getTop() - scrollY
                    || y >= child.getBottom() - scrollY
                    || x < child.getLeft()
                    || x >= child.getRight());
        }
@@ -452,6 +453,9 @@ public class ScrollView extends FrameLayout {
                /* Release the drag */
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {
                    invalidate();
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
@@ -483,6 +487,11 @@ public class ScrollView extends FrameLayout {

        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                final float y = ev.getY();
                if (!(mIsBeingDragged = inChild((int) ev.getX(), (int) y))) {
                    return false;
                }
                
                /*
                 * If being flinged and user touches, stop the fling. isFinished
                 * will be false if being flinged.
@@ -491,11 +500,6 @@ public class ScrollView extends FrameLayout {
                    mScroller.abortAnimation();
                }

                final float y = ev.getY();
                if (!(mIsBeingDragged = inChild((int) ev.getX(), (int) y))) {
                    return false;
                }
                
                // Remember where the motion event started
                mLastMotionY = y;
                mActivePointerId = ev.getPointerId(0);
@@ -542,6 +546,19 @@ public class ScrollView extends FrameLayout {
                    }
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                if (mIsBeingDragged && getChildCount() > 0) {
                    if (mScroller.springback(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {
                        invalidate();
                    }
                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;
                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;