summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2010-02-24 18:30:14 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-02-24 18:30:14 -0800
commit9d6e45ad9213b3cf85e3a4ad037b4e9b182a4cc7 (patch)
treeda49bcc4815744ecb8eb713437012a0669fdb576 /core/java
parentfa0e57fbe77d46039f9e9a54512dce13f71773b5 (diff)
parentbc4e7533b9c6a6e45e3cf4a889bcb913b8feefc5 (diff)
downloadframeworks_base-9d6e45ad9213b3cf85e3a4ad037b4e9b182a4cc7.zip
frameworks_base-9d6e45ad9213b3cf85e3a4ad037b4e9b182a4cc7.tar.gz
frameworks_base-9d6e45ad9213b3cf85e3a4ad037b4e9b182a4cc7.tar.bz2
Merge "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.java80
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) {