summaryrefslogtreecommitdiffstats
path: root/core/java
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2010-02-25 16:29:42 -0800
committerAndroid (Google) Code Review <android-gerrit@google.com>2010-02-25 16:29:42 -0800
commit4bb79db462a65381e85715da582bdd7fe278fd52 (patch)
tree140bbcacd71b02e8a27f7d3b38c9a690a5df73ec /core/java
parent7bc58b07e285067618bb2de78fbdf1545dcf01a6 (diff)
parent4cd47702f00a2fd6d6bc16c5398edb884d98bdca (diff)
downloadframeworks_base-4bb79db462a65381e85715da582bdd7fe278fd52.zip
frameworks_base-4bb79db462a65381e85715da582bdd7fe278fd52.tar.gz
frameworks_base-4bb79db462a65381e85715da582bdd7fe278fd52.tar.bz2
Merge "HorizontalScrollView multitouch scroll and only grip on content AbsListView multitouch scroll and only grip on content"
Diffstat (limited to 'core/java')
-rw-r--r--core/java/android/widget/AbsListView.java117
-rw-r--r--core/java/android/widget/GridView.java2
-rw-r--r--core/java/android/widget/HorizontalScrollView.java137
-rw-r--r--core/java/android/widget/ListView.java1
-rw-r--r--core/java/android/widget/ScrollView.java4
5 files changed, 208 insertions, 53 deletions
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9ddfeff..a9b746a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -467,6 +467,18 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// True when the popup should be hidden because of a call to
// dispatchDisplayHint()
private boolean mPopupHidden;
+
+ /**
+ * 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;
/**
* Interface definition for a callback to be invoked when the list or grid
@@ -1995,8 +2007,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
final int action = ev.getAction();
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
View v;
int deltaY;
@@ -2006,18 +2016,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
mVelocityTracker.addMovement(ev);
- switch (action) {
+ switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
switch (mTouchMode) {
case TOUCH_MODE_OVERFLING: {
mFlingRunnable.endFling();
mTouchMode = TOUCH_MODE_OVERSCROLL;
- mLastY = y;
+ mLastY = (int) ev.getY();
mMotionCorrection = 0;
+ mActivePointerId = ev.getPointerId(0);
break;
}
default: {
+ mActivePointerId = ev.getPointerId(0);
+ final int x = (int) ev.getX();
+ final int y = (int) ev.getY();
int motionPosition = pointToPosition(x, y);
if (!mDataChanged) {
if ((mTouchMode != TOUCH_MODE_FLING) && (motionPosition >= 0)
@@ -2037,12 +2051,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// code in ViewRoot to try to find a nearby view to select
return false;
}
- // User clicked on whitespace, or stopped a fling. It is a scroll.
- createScrollingCache();
- mTouchMode = TOUCH_MODE_SCROLL;
- mMotionCorrection = 0;
- motionPosition = findMotionRow(y);
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+
+ if (mTouchMode == TOUCH_MODE_FLING) {
+ // Stopped a fling. It is a scroll.
+ createScrollingCache();
+ mTouchMode = TOUCH_MODE_SCROLL;
+ mMotionCorrection = 0;
+ motionPosition = findMotionRow(y);
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
+ }
}
}
@@ -2062,6 +2079,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
case MotionEvent.ACTION_MOVE: {
+ final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ final int y = (int) ev.getY(pointerIndex);
deltaY = y - mMotionY;
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
@@ -2142,7 +2161,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
// We did not scroll the full amount. Treat this essentially like the
// start of a new touch scroll
- final int motionPosition = findMotionRow(y);
+ final int motionPosition = findClosestMotionRow(y);
mMotionCorrection = 0;
motionView = getChildAt(motionPosition - mFirstPosition);
@@ -2238,7 +2257,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
} else {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- final int initialVelocity = (int) velocityTracker.getYVelocity();
+ final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
if (Math.abs(initialVelocity) > mMinimumVelocity) {
if (mFlingRunnable == null) {
@@ -2264,7 +2283,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- final int initialVelocity = (int) velocityTracker.getYVelocity();
+ final int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING);
if (Math.abs(initialVelocity) > mMinimumVelocity) {
@@ -2290,6 +2309,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mVelocityTracker.recycle();
mVelocityTracker = null;
}
+
+ mActivePointerId = INVALID_POINTER;
if (PROFILE_SCROLLING) {
if (mScrollProfilingStarted) {
@@ -2332,6 +2353,24 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mVelocityTracker = null;
}
}
+
+ mActivePointerId = INVALID_POINTER;
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ onSecondaryPointerUp(ev);
+ final int x = mMotionX;
+ final int y = mMotionY;
+ final int motionPosition = pointToPosition(x, y);
+ if (motionPosition >= 0) {
+ // Remember where the motion event started
+ v = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = v.getTop();
+ mMotionPosition = motionPosition;
+ }
+ mLastY = y;
+ break;
}
}
@@ -2380,8 +2419,6 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int action = ev.getAction();
- int x = (int) ev.getX();
- int y = (int) ev.getY();
View v;
if (mFastScroller != null) {
@@ -2391,13 +2428,17 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
- switch (action) {
+ switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN: {
int touchMode = mTouchMode;
if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
return true;
}
+ final int x = (int) ev.getX();
+ final int y = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
+
int motionPosition = findMotionRow(y);
if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
// User clicked on an actual view (and was not stopping a fling).
@@ -2420,6 +2461,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
case MotionEvent.ACTION_MOVE: {
switch (mTouchMode) {
case TOUCH_MODE_DOWN:
+ final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ final int y = (int) ev.getY(pointerIndex);
if (startScrollIfNeeded(y - mMotionY)) {
return true;
}
@@ -2430,13 +2473,37 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
case MotionEvent.ACTION_UP: {
mTouchMode = TOUCH_MODE_REST;
+ mActivePointerId = INVALID_POINTER;
reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
break;
}
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ onSecondaryPointerUp(ev);
+ break;
+ }
}
return false;
}
+
+ 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;
+ mMotionX = (int) ev.getX(newPointerIndex);
+ mMotionY = (int) ev.getY(newPointerIndex);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ }
+ }
/**
* {@inheritDoc}
@@ -3150,9 +3217,25 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* Find the row closest to y. This row will be used as the motion row when scrolling
*
* @param y Where the user touched
- * @return The position of the first (or only) item in the row closest to y
+ * @return The position of the first (or only) item in the row containing y
*/
abstract int findMotionRow(int y);
+
+ /**
+ * Find the row closest to y. This row will be used as the motion row when scrolling.
+ *
+ * @param y Where the user touched
+ * @return The position of the first (or only) item in the row closest to y
+ */
+ int findClosestMotionRow(int y) {
+ final int childCount = getChildCount();
+ if (childCount == 0) {
+ return INVALID_POSITION;
+ }
+
+ final int motionRow = findMotionRow(y);
+ return motionRow != INVALID_POSITION ? motionRow : mFirstPosition + childCount - 1;
+ }
/**
* Causes all the views to be rebuilt and redrawn.
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index b9acf5e..9e930a5 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -431,8 +431,6 @@ public class GridView extends AbsListView {
}
}
}
-
- return mFirstPosition + childCount - 1;
}
return INVALID_POSITION;
}
diff --git a/core/java/android/widget/HorizontalScrollView.java b/core/java/android/widget/HorizontalScrollView.java
index a7b819a..acb7e02 100644
--- a/core/java/android/widget/HorizontalScrollView.java
+++ b/core/java/android/widget/HorizontalScrollView.java
@@ -116,7 +116,19 @@ public class HorizontalScrollView 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 HorizontalScrollView(Context context) {
this(context, null);
}
@@ -362,6 +374,17 @@ public class HorizontalScrollView extends FrameLayout {
return handled;
}
+ private boolean inChild(int x, int y) {
+ if (getChildCount() > 0) {
+ final View child = getChildAt(0);
+ return !(y < child.getTop()
+ || y >= child.getBottom()
+ || x < child.getLeft()
+ || x >= child.getRight());
+ }
+ return false;
+ }
+
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
@@ -380,10 +403,8 @@ public class HorizontalScrollView extends FrameLayout {
return true;
}
- final float x = ev.getX();
-
- 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.
@@ -393,16 +414,30 @@ public class HorizontalScrollView extends FrameLayout {
* Locally do absolute value. mLastMotionX is set to the x value
* of the down event.
*/
+ final int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ final float x = ev.getX(pointerIndex);
final int xDiff = (int) Math.abs(x - mLastMotionX);
if (xDiff > mTouchSlop) {
mIsBeingDragged = true;
+ mLastMotionX = x;
if (mParent != null) mParent.requestDisallowInterceptTouchEvent(true);
}
break;
+ }
- case MotionEvent.ACTION_DOWN:
- /* Remember location of down touch */
+ case MotionEvent.ACTION_DOWN: {
+ final float x = ev.getX();
+ if (!inChild((int) x, (int) ev.getY())) {
+ mIsBeingDragged = false;
+ break;
+ }
+
+ /*
+ * Remember location of down touch.
+ * ACTION_DOWN always refers to pointer index 0.
+ */
mLastMotionX = x;
+ mActivePointerId = ev.getPointerId(0);
/*
* If being flinged and user touches the screen, initiate drag;
@@ -411,11 +446,16 @@ public class HorizontalScrollView 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;
}
@@ -441,10 +481,9 @@ public class HorizontalScrollView extends FrameLayout {
mVelocityTracker.addMovement(ev);
final int action = ev.getAction();
- final float x = ev.getX();
- 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.
@@ -452,42 +491,78 @@ public class HorizontalScrollView extends FrameLayout {
if (!mScroller.isFinished()) {
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;
break;
+ }
case MotionEvent.ACTION_MOVE:
- // Scroll to follow the motion event
- final int deltaX = (int) (mLastMotionX - x);
- mLastMotionX = x;
-
- overscrollBy(deltaX, 0, mScrollX, 0, getScrollRange(), 0,
- getOverscrollMax(), 0);
+ if (mIsBeingDragged) {
+ // Scroll to follow the motion event
+ final int activePointerIndex = ev.findPointerIndex(mActivePointerId);
+ final float x = ev.getX(activePointerIndex);
+ final int deltaX = (int) (mLastMotionX - x);
+ mLastMotionX = x;
+
+ overscrollBy(deltaX, 0, mScrollX, 0, getScrollRange(), 0,
+ getOverscrollMax(), 0);
+ }
break;
case MotionEvent.ACTION_UP:
- final VelocityTracker velocityTracker = mVelocityTracker;
- velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
- int initialVelocity = (int) velocityTracker.getXVelocity();
-
- if (getChildCount() > 0) {
- if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
- fling(-initialVelocity);
- } else {
- final int right = getScrollRange();
- if (mScroller.springback(mScrollX, mScrollY, 0, 0, right, 0)) {
- invalidate();
+ if (mIsBeingDragged) {
+ final VelocityTracker velocityTracker = mVelocityTracker;
+ velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
+ int initialVelocity = (int) velocityTracker.getXVelocity(mActivePointerId);
+
+ if (getChildCount() > 0) {
+ if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+ fling(-initialVelocity);
+ } else {
+ final int right = getScrollRange();
+ if (mScroller.springback(mScrollX, mScrollY, 0, 0, right, 0)) {
+ invalidate();
+ }
}
}
- }
+
+ mActivePointerId = INVALID_POINTER;
+ mIsBeingDragged = false;
- if (mVelocityTracker != null) {
- mVelocityTracker.recycle();
- mVelocityTracker = null;
+ 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;
+ mLastMotionX = ev.getX(newPointerIndex);
+ mActivePointerId = ev.getPointerId(newPointerIndex);
+ if (mVelocityTracker != null) {
+ mVelocityTracker.clear();
+ }
+ }
+ }
+
@Override
protected void onOverscrolled(int scrollX, int scrollY,
boolean clampedX, boolean clampedY) {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 8d688a5..51a1ef2 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1192,7 +1192,6 @@ public class ListView extends AbsListView {
return mFirstPosition + i;
}
}
- return mFirstPosition + childCount - 1;
}
return INVALID_POSITION;
}
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index fd24058..489c44d 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -427,7 +427,7 @@ public class ScrollView extends FrameLayout {
case MotionEvent.ACTION_DOWN: {
final float y = ev.getY();
- if (!inChild((int)ev.getX(), (int)y)) {
+ if (!inChild((int) ev.getX(), (int) y)) {
mIsBeingDragged = false;
break;
}
@@ -493,7 +493,7 @@ public class ScrollView extends FrameLayout {
}
final float y = ev.getY();
- if (!(mIsBeingDragged = inChild((int)ev.getX(), (int)y))) {
+ if (!(mIsBeingDragged = inChild((int) ev.getX(), (int) y))) {
return false;
}