diff options
author | Adam Powell <adamp@google.com> | 2010-02-23 14:49:01 -0800 |
---|---|---|
committer | Adam Powell <adamp@google.com> | 2010-02-24 18:22:08 -0800 |
commit | bc4e7533b9c6a6e45e3cf4a889bcb913b8feefc5 (patch) | |
tree | f35c151524ac9aa35d3fe30d7272c8d3bac17d16 /core/java | |
parent | 618c8f1ede12d81fc4fee3d6fb239940f7e2023d (diff) | |
download | frameworks_base-bc4e7533b9c6a6e45e3cf4a889bcb913b8feefc5.zip frameworks_base-bc4e7533b9c6a6e45e3cf4a889bcb913b8feefc5.tar.gz frameworks_base-bc4e7533b9c6a6e45e3cf4a889bcb913b8feefc5.tar.bz2 |
ScrollView multiple pointer support. Fixed a bug where ScrollView
wouldn't scroll if the initially tapped child ignores the down event.
Diffstat (limited to 'core/java')
-rw-r--r-- | core/java/android/widget/ScrollView.java | 80 |
1 files changed, 65 insertions, 15 deletions
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index bb3b07e..fd24058 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -115,6 +115,18 @@ public class ScrollView extends FrameLayout { private int mTouchSlop; 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; } - case MotionEvent.ACTION_UP: + 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) { |