OSDN Git Service

Track persistent nested Y offset for fling velocity
authorAdam Powell <adamp@google.com>
Mon, 22 Sep 2014 16:47:48 +0000 (09:47 -0700)
committerAdam Powell <adamp@google.com>
Tue, 23 Sep 2014 00:18:42 +0000 (17:18 -0700)
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
core/java/android/widget/ScrollView.java

index af53ec8..2b8b4dc 100644 (file)
@@ -611,6 +611,12 @@ public abstract class AbsListView extends AdapterView<ListAdapter> 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<ListAdapter> 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<ListAdapter> 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<ListAdapter> 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<ListAdapter> 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<ListAdapter> 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<ListAdapter> implements Te
             mLastY = Integer.MIN_VALUE;
             initOrResetVelocityTracker();
             mVelocityTracker.addMovement(ev);
+            mNestedYOffset = 0;
             startNestedScroll(SCROLL_AXIS_VERTICAL);
             if (touchMode == TOUCH_MODE_FLING) {
                 return true;
index dd312a6..a90b392 100644 (file)
@@ -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) {