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

Commit 9d6e45ad authored by Adam Powell's avatar Adam Powell Committed by Android (Google) Code Review
Browse files

Merge "ScrollView multiple pointer support. Fixed a bug where ScrollView...

Merge "ScrollView multiple pointer support. Fixed a bug where ScrollView wouldn't scroll if the initially tapped child ignores the down event."
parents fa0e57fb bc4e7533
Loading
Loading
Loading
Loading
+65 −15
Original line number Diff line number Diff line
@@ -116,6 +116,18 @@ public class ScrollView extends FrameLayout {
    private int mMinimumVelocity;
    private int mMaximumVelocity;
    
    /**
     * ID of the active pointer. This is used to retain consistency during
     * drags/flings if multiple pointers are used.
     */
    private int mActivePointerId = INVALID_POINTER;
    
    /**
     * Sentinel value for no current active pointer.
     * Used by {@link #mActivePointerId}.
     */
    private static final int INVALID_POINTER = -1;

    public ScrollView(Context context) {
        this(context, null);
    }
@@ -392,10 +404,8 @@ public class ScrollView extends FrameLayout {
            return true;
        }

        final float y = ev.getY();

        switch (action) {
            case MotionEvent.ACTION_MOVE:
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_MOVE: {
                /*
                 * mIsBeingDragged == false, otherwise the shortcut would have caught it. Check
                 * whether the user has moved far enough from his original down touch.
@@ -405,21 +415,29 @@ public class ScrollView extends FrameLayout {
                * Locally do absolute value. mLastMotionY is set to the y value
                * of the down event.
                */
                final int pointerIndex = ev.findPointerIndex(mActivePointerId);
                final float y = ev.getY(pointerIndex);
                final int yDiff = (int) Math.abs(y - mLastMotionY);
                if (yDiff > mTouchSlop) {
                    mIsBeingDragged = true;
                    mLastMotionY = y;
                }
                break;
            }

            case MotionEvent.ACTION_DOWN:
            case MotionEvent.ACTION_DOWN: {
                final float y = ev.getY();
                if (!inChild((int)ev.getX(), (int)y)) {
                    mIsBeingDragged = false;
                    break;
                }

                /* Remember location of down touch */
                /*
                 * Remember location of down touch.
                 * ACTION_DOWN always refers to pointer index 0.
                 */
                mLastMotionY = y;
                mActivePointerId = ev.getPointerId(0);

                /*
                * If being flinged and user touches the screen, initiate drag;
@@ -428,11 +446,16 @@ public class ScrollView extends FrameLayout {
                */
                mIsBeingDragged = !mScroller.isFinished();
                break;
            }

            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                /* Release the drag */
                mIsBeingDragged = false;
                mActivePointerId = INVALID_POINTER;
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }

@@ -458,10 +481,9 @@ public class ScrollView extends FrameLayout {
        mVelocityTracker.addMovement(ev);

        final int action = ev.getAction();
        final float y = ev.getY();

        switch (action) {
            case MotionEvent.ACTION_DOWN:
        switch (action & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN: {
                /*
                * If being flinged and user touches, stop the fling. isFinished
                * will be false if being flinged.
@@ -470,29 +492,33 @@ public class ScrollView extends FrameLayout {
                    mScroller.abortAnimation();
                }

                if (!inChild((int)ev.getX(), (int)y)) {
                    mIsBeingDragged = false;
                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);
                break;
            }
            case MotionEvent.ACTION_MOVE:
                if (mIsBeingDragged) {
                    // Scroll to follow the motion event
                    final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                    final float y = ev.getY(activePointerIndex);
                    final int deltaY = (int) (mLastMotionY - y);
                    mLastMotionY = y;

                    overscrollBy(0, deltaY, 0, mScrollY, 0, getScrollRange(),
                            0, getOverscrollMax());
                    break;
                }
                break;
            case MotionEvent.ACTION_UP: 
                if (mIsBeingDragged) {
                    final VelocityTracker velocityTracker = mVelocityTracker;
                    velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                    int initialVelocity = (int) velocityTracker.getYVelocity();
                    int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);

                    if (getChildCount() > 0) {
                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
@@ -505,15 +531,39 @@ public class ScrollView extends FrameLayout {
                        }
                    }

                    mActivePointerId = INVALID_POINTER;
                    mIsBeingDragged = false;

                    if (mVelocityTracker != null) {
                        mVelocityTracker.recycle();
                        mVelocityTracker = null;
                    }
                }
                break;
            case MotionEvent.ACTION_POINTER_UP:
                onSecondaryPointerUp(ev);
                break;
        }
        return true;
    }
    
    private void onSecondaryPointerUp(MotionEvent ev) {
        final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
                MotionEvent.ACTION_POINTER_INDEX_SHIFT;
        final int pointerId = ev.getPointerId(pointerIndex);
        if (pointerId == mActivePointerId) {
            // This was our active pointer going up. Choose a new
            // active pointer and adjust accordingly.
            // TODO: Make this decision more intelligent.
            final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
            mLastMotionY = ev.getY(newPointerIndex);
            mActivePointerId = ev.getPointerId(newPointerIndex);
            if (mVelocityTracker != null) {
                mVelocityTracker.clear();
            }
        }
    }
    
    @Override
    protected void onOverscrolled(int scrollX, int scrollY,
            boolean clampedX, boolean clampedY) {