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
This commit is contained in:
@@ -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,21 +490,22 @@ public class HorizontalScrollView extends FrameLayout {
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -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,19 +487,19 @@ public class ScrollView extends FrameLayout {
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
if (!mScroller.isFinished()) {
|
||||
mScroller.abortAnimation();
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
Reference in New Issue
Block a user