summaryrefslogtreecommitdiffstats
path: root/core/java/android/widget/ScrollView.java
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android/widget/ScrollView.java')
-rw-r--r--core/java/android/widget/ScrollView.java76
1 files changed, 61 insertions, 15 deletions
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 082d728..34a6a40 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -138,6 +138,12 @@ public class ScrollView extends FrameLayout {
private int mActivePointerId = INVALID_POINTER;
/**
+ * Used during scrolling to retrieve the new offset within the window.
+ */
+ private final int[] mScrollOffset = new int[2];
+ private final int[] mScrollConsumed = new int[2];
+
+ /**
* The StrictMode "critical time span" objects to catch animation
* stutters. Non-null when a time-sensitive animation is
* in-flight. Must call finish() on them when done animating.
@@ -505,7 +511,7 @@ public class ScrollView extends FrameLayout {
final int y = (int) ev.getY(pointerIndex);
final int yDiff = Math.abs(y - mLastMotionY);
- if (yDiff > mTouchSlop) {
+ if (yDiff > mTouchSlop && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
mIsBeingDragged = true;
mLastMotionY = y;
initVelocityTrackerIfNotExists();
@@ -606,6 +612,7 @@ public class ScrollView extends FrameLayout {
// Remember where the motion event started
mLastMotionY = (int) ev.getY();
mActivePointerId = ev.getPointerId(0);
+ startNestedScroll(SCROLL_AXIS_VERTICAL);
break;
}
case MotionEvent.ACTION_MOVE:
@@ -617,6 +624,9 @@ public class ScrollView extends FrameLayout {
final int y = (int) ev.getY(activePointerIndex);
int deltaY = mLastMotionY - y;
+ if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
+ deltaY -= mScrollConsumed[1] + mScrollOffset[1];
+ }
if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
final ViewParent parent = getParent();
if (parent != null) {
@@ -633,22 +643,25 @@ public class ScrollView extends FrameLayout {
// Scroll to follow the motion event
mLastMotionY = y;
- final int oldX = mScrollX;
final int oldY = mScrollY;
final int range = getScrollRange();
final int overscrollMode = getOverScrollMode();
- final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+ boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
// Calling overScrollBy will call onOverScrolled, which
// calls onScrollChanged if applicable.
- if (overScrollBy(0, deltaY, 0, mScrollY,
- 0, range, 0, mOverscrollDistance, true)) {
+ if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)
+ && !hasNestedScrollingParent()) {
// Break our velocity if we hit a scroll barrier.
mVelocityTracker.clear();
}
- if (canOverscroll) {
+ final int scrolledDeltaY = mScrollY - oldY;
+ final int unconsumedY = deltaY - scrolledDeltaY;
+ if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
+ mLastMotionY -= mScrollOffset[1];
+ } else if (canOverscroll) {
final int pulledToY = oldY + deltaY;
if (pulledToY < 0) {
mEdgeGlowTop.onPull((float) deltaY / getHeight());
@@ -674,15 +687,11 @@ public class ScrollView extends FrameLayout {
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if (getChildCount() > 0) {
- if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
- fling(-initialVelocity);
- } else {
- if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,
- getScrollRange())) {
- postInvalidateOnAnimation();
- }
- }
+ if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+ flingWithNestedDispatch(-initialVelocity);
+ } else if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,
+ getScrollRange())) {
+ postInvalidateOnAnimation();
}
mActivePointerId = INVALID_POINTER;
@@ -1553,6 +1562,15 @@ public class ScrollView extends FrameLayout {
}
}
+ private void flingWithNestedDispatch(int velocityY) {
+ if (mScrollY == 0 && velocityY < 0 ||
+ mScrollY == getScrollRange() && velocityY > 0) {
+ dispatchNestedFling(0, velocityY);
+ } else {
+ fling(velocityY);
+ }
+ }
+
private void endDrag() {
mIsBeingDragged = false;
@@ -1603,6 +1621,34 @@ public class ScrollView extends FrameLayout {
}
@Override
+ public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+ return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public void onStopNestedScroll(View target) {
+ super.onStopNestedScroll(target);
+ }
+
+ @Override
+ public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+ int dxUnconsumed, int dyUnconsumed) {
+ scrollBy(0, dyUnconsumed);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean onNestedFling(View target, float velocityX, float velocityY) {
+ flingWithNestedDispatch((int) velocityY);
+ return true;
+ }
+
+ @Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (mEdgeGlowTop != null) {