From 744beffb6ae76d682c559970bb634722c835a32e Mon Sep 17 00:00:00 2001 From: Adam Powell Date: Mon, 22 Sep 2014 09:47:48 -0700 Subject: [PATCH] Track persistent nested Y offset for fling velocity Track the nested offsets applied persistently in AbsListView and ScrollView. This allows accurate velocity to be reported to nested fling/pre-fling. Bug 17548219 Change-Id: I66199c534aca7fb81746eff6d04c931e4c4e48da --- core/java/android/widget/AbsListView.java | 17 +++++++++++++++-- core/java/android/widget/ScrollView.java | 13 +++++++++++-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java index af53ec85b7c36..2b8b4dce72a35 100644 --- a/core/java/android/widget/AbsListView.java +++ b/core/java/android/widget/AbsListView.java @@ -611,6 +611,12 @@ public abstract class AbsListView extends AdapterView implements Te private final int[] mScrollOffset = new int[2]; private final int[] mScrollConsumed = new int[2]; + // Used for offsetting MotionEvents that we feed to the VelocityTracker. + // In the future it would be nice to be able to give this to the VelocityTracker + // directly, or alternatively put a VT into absolute-positioning mode that only + // reads the raw screen-coordinate x/y values. + private int mNestedYOffset = 0; + // True when the popup should be hidden because of a call to // dispatchDisplayHint() private boolean mPopupHidden; @@ -3330,6 +3336,7 @@ public abstract class AbsListView extends AdapterView implements Te scrollConsumedCorrection = mScrollConsumed[1]; if (vtev != null) { vtev.offsetLocation(0, mScrollOffset[1]); + mNestedYOffset += mScrollOffset[1]; } } final int deltaY = rawDeltaY; @@ -3399,6 +3406,7 @@ public abstract class AbsListView extends AdapterView implements Te lastYCorrection -= mScrollOffset[1]; if (vtev != null) { vtev.offsetLocation(0, mScrollOffset[1]); + mNestedYOffset += mScrollOffset[1]; } } else { final boolean atOverscrollEdge = overScrollBy(0, overscroll, @@ -3582,6 +3590,10 @@ public abstract class AbsListView extends AdapterView implements Te final MotionEvent vtev = MotionEvent.obtain(ev); final int actionMasked = ev.getActionMasked(); + if (actionMasked == MotionEvent.ACTION_DOWN) { + mNestedYOffset = 0; + } + vtev.offsetLocation(0, mNestedYOffset); switch (actionMasked) { case MotionEvent.ACTION_DOWN: { onTouchDown(ev); @@ -4144,7 +4156,7 @@ public abstract class AbsListView extends AdapterView implements Te @Override public boolean onInterceptTouchEvent(MotionEvent ev) { - int action = ev.getAction(); + final int actionMasked = ev.getActionMasked(); View v; if (mPositionScroller != null) { @@ -4163,7 +4175,7 @@ public abstract class AbsListView extends AdapterView implements Te return true; } - switch (action & MotionEvent.ACTION_MASK) { + switch (actionMasked) { case MotionEvent.ACTION_DOWN: { int touchMode = mTouchMode; if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) { @@ -4190,6 +4202,7 @@ public abstract class AbsListView extends AdapterView implements Te mLastY = Integer.MIN_VALUE; initOrResetVelocityTracker(); mVelocityTracker.addMovement(ev); + mNestedYOffset = 0; startNestedScroll(SCROLL_AXIS_VERTICAL); if (touchMode == TOUCH_MODE_FLING) { return true; diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java index dd312a664c96a..a90b39247a0a5 100644 --- a/core/java/android/widget/ScrollView.java +++ b/core/java/android/widget/ScrollView.java @@ -142,6 +142,7 @@ public class ScrollView extends FrameLayout { */ private final int[] mScrollOffset = new int[2]; private final int[] mScrollConsumed = new int[2]; + private int mNestedYOffset; /** * The StrictMode "critical time span" objects to catch animation @@ -516,6 +517,7 @@ public class ScrollView extends FrameLayout { mLastMotionY = y; initVelocityTrackerIfNotExists(); mVelocityTracker.addMovement(ev); + mNestedYOffset = 0; if (mScrollStrictSpan == null) { mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll"); } @@ -586,9 +588,14 @@ public class ScrollView extends FrameLayout { MotionEvent vtev = MotionEvent.obtain(ev); - final int action = ev.getAction(); + final int actionMasked = ev.getActionMasked(); - switch (action & MotionEvent.ACTION_MASK) { + if (actionMasked == MotionEvent.ACTION_DOWN) { + mNestedYOffset = 0; + } + vtev.offsetLocation(0, mNestedYOffset); + + switch (actionMasked) { case MotionEvent.ACTION_DOWN: { if (getChildCount() == 0) { return false; @@ -630,6 +637,7 @@ public class ScrollView extends FrameLayout { if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) { deltaY -= mScrollConsumed[1]; vtev.offsetLocation(0, mScrollOffset[1]); + mNestedYOffset += mScrollOffset[1]; } if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) { final ViewParent parent = getParent(); @@ -666,6 +674,7 @@ public class ScrollView extends FrameLayout { if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) { mLastMotionY -= mScrollOffset[1]; vtev.offsetLocation(0, mScrollOffset[1]); + mNestedYOffset += mScrollOffset[1]; } else if (canOverscroll) { final int pulledToY = oldY + deltaY; if (pulledToY < 0) {