Loading core/java/android/widget/AbsListView.java +36 −17 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,8 @@ import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection; Loading Loading @@ -659,6 +661,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ */ private int mLastHandledItemCount; private int mLastHandledItemCount; /** * Used for smooth scrolling at a consistent rate */ static final Interpolator sLinearInterpolator = new LinearInterpolator(); /** /** * Interface definition for a callback to be invoked when the list or grid * Interface definition for a callback to be invoked when the list or grid * has been scrolled. * has been scrolled. Loading Loading @@ -3753,6 +3760,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te void start(int initialVelocity) { void start(int initialVelocity) { int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mLastFlingY = initialY; mScroller.setInterpolator(null); mScroller.fling(0, initialY, 0, initialVelocity, mScroller.fling(0, initialY, 0, initialVelocity, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); mTouchMode = TOUCH_MODE_FLING; mTouchMode = TOUCH_MODE_FLING; Loading Loading @@ -3782,6 +3790,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } void startOverfling(int initialVelocity) { void startOverfling(int initialVelocity) { mScroller.setInterpolator(null); mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight()); Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight()); mTouchMode = TOUCH_MODE_OVERFLING; mTouchMode = TOUCH_MODE_OVERFLING; Loading Loading @@ -3811,9 +3820,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te postOnAnimation(this); postOnAnimation(this); } } void startScroll(int distance, int duration) { void startScroll(int distance, int duration, boolean linear) { int initialY = distance < 0 ? Integer.MAX_VALUE : 0; int initialY = distance < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mLastFlingY = initialY; mScroller.setInterpolator(linear ? sLinearInterpolator : null); mScroller.startScroll(0, initialY, 0, distance, duration); mScroller.startScroll(0, initialY, 0, distance, duration); mTouchMode = TOUCH_MODE_FLING; mTouchMode = TOUCH_MODE_FLING; postOnAnimation(this); postOnAnimation(this); Loading Loading @@ -4107,14 +4117,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } else { } else { // On-screen, just scroll. // On-screen, just scroll. final int targetTop = getChildAt(position - firstPos).getTop(); final int targetTop = getChildAt(position - firstPos).getTop(); smoothScrollBy(targetTop - offset, duration); smoothScrollBy(targetTop - offset, duration, true); return; return; } } // Estimate how many screens we should travel // Estimate how many screens we should travel final float screenTravelCount = (float) viewTravelCount / childCount; final float screenTravelCount = (float) viewTravelCount / childCount; mScrollDuration = screenTravelCount < 1 ? (int) (screenTravelCount * duration) : mScrollDuration = screenTravelCount < 1 ? (int) (duration / screenTravelCount); duration : (int) (duration / screenTravelCount); mLastSeenPos = INVALID_POSITION; mLastSeenPos = INVALID_POSITION; postOnAnimation(this); postOnAnimation(this); Loading Loading @@ -4151,7 +4161,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom; Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom; final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll; final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll; smoothScrollBy(scrollBy, mScrollDuration); smoothScrollBy(scrollBy, mScrollDuration, true); mLastSeenPos = lastPos; mLastSeenPos = lastPos; if (lastPos < mTargetPos) { if (lastPos < mTargetPos) { Loading Loading @@ -4182,14 +4192,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll); final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll); if (nextPos < mBoundPos) { if (nextPos < mBoundPos) { smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll), smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll), mScrollDuration); mScrollDuration, true); mLastSeenPos = nextPos; mLastSeenPos = nextPos; postOnAnimation(this); postOnAnimation(this); } else { } else { if (nextViewTop > extraScroll) { if (nextViewTop > extraScroll) { smoothScrollBy(nextViewTop - extraScroll, mScrollDuration); smoothScrollBy(nextViewTop - extraScroll, mScrollDuration, true); } } } } break; break; Loading @@ -4210,7 +4220,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = firstPos > 0 ? final int extraScroll = firstPos > 0 ? Math.max(mExtraScroll, mListPadding.top) : mListPadding.top; Math.max(mExtraScroll, mListPadding.top) : mListPadding.top; smoothScrollBy(firstViewTop - extraScroll, mScrollDuration); smoothScrollBy(firstViewTop - extraScroll, mScrollDuration, true); mLastSeenPos = firstPos; mLastSeenPos = firstPos; Loading @@ -4229,7 +4239,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (lastPos == mLastSeenPos) { if (lastPos == mLastSeenPos) { // No new views, let things keep going. // No new views, let things keep going. post(this); postOnAnimation(this); return; return; } } Loading @@ -4240,13 +4250,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = Math.max(mListPadding.top, mExtraScroll); final int extraScroll = Math.max(mListPadding.top, mExtraScroll); mLastSeenPos = lastPos; mLastSeenPos = lastPos; if (lastPos > mBoundPos) { if (lastPos > mBoundPos) { smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration); smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration, true); postOnAnimation(this); postOnAnimation(this); } else { } else { final int bottom = listHeight - extraScroll; final int bottom = listHeight - extraScroll; final int lastViewBottom = lastViewTop + lastViewHeight; final int lastViewBottom = lastViewTop + lastViewHeight; if (bottom > lastViewBottom) { if (bottom > lastViewBottom) { smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration); smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration, true); } } } } break; break; Loading @@ -4255,7 +4265,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case MOVE_OFFSET: { case MOVE_OFFSET: { if (mLastSeenPos == firstPos) { if (mLastSeenPos == firstPos) { // No new views, let things keep going. // No new views, let things keep going. post(this); postOnAnimation(this); return; return; } } Loading @@ -4277,17 +4287,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final float modifier = Math.min(Math.abs(screenTravelCount), 1.f); final float modifier = Math.min(Math.abs(screenTravelCount), 1.f); if (position < firstPos) { if (position < firstPos) { smoothScrollBy((int) (-getHeight() * modifier), mScrollDuration); final int distance = (int) (-getHeight() * modifier); final int duration = (int) (mScrollDuration * modifier); smoothScrollBy(distance, duration, true); postOnAnimation(this); postOnAnimation(this); } else if (position > lastPos) { } else if (position > lastPos) { smoothScrollBy((int) (getHeight() * modifier), mScrollDuration); final int distance = (int) (getHeight() * modifier); final int duration = (int) (mScrollDuration * modifier); smoothScrollBy(distance, duration, true); postOnAnimation(this); postOnAnimation(this); } else { } else { // On-screen, just scroll. // On-screen, just scroll. final int targetTop = getChildAt(position - firstPos).getTop(); final int targetTop = getChildAt(position - firstPos).getTop(); final int distance = targetTop - mOffsetFromTop; final int distance = targetTop - mOffsetFromTop; smoothScrollBy(distance, final int duration = (int) (mScrollDuration * (int) (mScrollDuration * ((float) distance / getHeight()))); ((float) Math.abs(distance) / getHeight())); smoothScrollBy(distance, duration, true); } } break; break; } } Loading Loading @@ -4393,6 +4408,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @param duration Duration of the scroll animation in milliseconds. * @param duration Duration of the scroll animation in milliseconds. */ */ public void smoothScrollBy(int distance, int duration) { public void smoothScrollBy(int distance, int duration) { smoothScrollBy(distance, duration, false); } void smoothScrollBy(int distance, int duration, boolean linear) { if (mFlingRunnable == null) { if (mFlingRunnable == null) { mFlingRunnable = new FlingRunnable(); mFlingRunnable = new FlingRunnable(); } } Loading @@ -4414,7 +4433,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } else { } else { reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); mFlingRunnable.startScroll(distance, duration); mFlingRunnable.startScroll(distance, duration, linear); } } } } Loading core/java/android/widget/OverScroller.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -35,7 +35,7 @@ public class OverScroller { private final SplineOverScroller mScrollerX; private final SplineOverScroller mScrollerX; private final SplineOverScroller mScrollerY; private final SplineOverScroller mScrollerY; private final Interpolator mInterpolator; private Interpolator mInterpolator; private final boolean mFlywheel; private final boolean mFlywheel; Loading Loading @@ -113,6 +113,10 @@ public class OverScroller { this(context, interpolator, flywheel); this(context, interpolator, flywheel); } } void setInterpolator(Interpolator interpolator) { mInterpolator = interpolator; } /** /** * The amount of friction applied to flings. The default value * The amount of friction applied to flings. The default value * is {@link ViewConfiguration#getScrollFriction}. * is {@link ViewConfiguration#getScrollFriction}. Loading Loading
core/java/android/widget/AbsListView.java +36 −17 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,8 @@ import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo; import android.view.animation.Interpolator; import android.view.animation.LinearInterpolator; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.BaseInputConnection; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputConnection; Loading Loading @@ -659,6 +661,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te */ */ private int mLastHandledItemCount; private int mLastHandledItemCount; /** * Used for smooth scrolling at a consistent rate */ static final Interpolator sLinearInterpolator = new LinearInterpolator(); /** /** * Interface definition for a callback to be invoked when the list or grid * Interface definition for a callback to be invoked when the list or grid * has been scrolled. * has been scrolled. Loading Loading @@ -3753,6 +3760,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te void start(int initialVelocity) { void start(int initialVelocity) { int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; int initialY = initialVelocity < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mLastFlingY = initialY; mScroller.setInterpolator(null); mScroller.fling(0, initialY, 0, initialVelocity, mScroller.fling(0, initialY, 0, initialVelocity, 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); 0, Integer.MAX_VALUE, 0, Integer.MAX_VALUE); mTouchMode = TOUCH_MODE_FLING; mTouchMode = TOUCH_MODE_FLING; Loading Loading @@ -3782,6 +3790,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } void startOverfling(int initialVelocity) { void startOverfling(int initialVelocity) { mScroller.setInterpolator(null); mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, mScroller.fling(0, mScrollY, 0, initialVelocity, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight()); Integer.MIN_VALUE, Integer.MAX_VALUE, 0, getHeight()); mTouchMode = TOUCH_MODE_OVERFLING; mTouchMode = TOUCH_MODE_OVERFLING; Loading Loading @@ -3811,9 +3820,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te postOnAnimation(this); postOnAnimation(this); } } void startScroll(int distance, int duration) { void startScroll(int distance, int duration, boolean linear) { int initialY = distance < 0 ? Integer.MAX_VALUE : 0; int initialY = distance < 0 ? Integer.MAX_VALUE : 0; mLastFlingY = initialY; mLastFlingY = initialY; mScroller.setInterpolator(linear ? sLinearInterpolator : null); mScroller.startScroll(0, initialY, 0, distance, duration); mScroller.startScroll(0, initialY, 0, distance, duration); mTouchMode = TOUCH_MODE_FLING; mTouchMode = TOUCH_MODE_FLING; postOnAnimation(this); postOnAnimation(this); Loading Loading @@ -4107,14 +4117,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } else { } else { // On-screen, just scroll. // On-screen, just scroll. final int targetTop = getChildAt(position - firstPos).getTop(); final int targetTop = getChildAt(position - firstPos).getTop(); smoothScrollBy(targetTop - offset, duration); smoothScrollBy(targetTop - offset, duration, true); return; return; } } // Estimate how many screens we should travel // Estimate how many screens we should travel final float screenTravelCount = (float) viewTravelCount / childCount; final float screenTravelCount = (float) viewTravelCount / childCount; mScrollDuration = screenTravelCount < 1 ? (int) (screenTravelCount * duration) : mScrollDuration = screenTravelCount < 1 ? (int) (duration / screenTravelCount); duration : (int) (duration / screenTravelCount); mLastSeenPos = INVALID_POSITION; mLastSeenPos = INVALID_POSITION; postOnAnimation(this); postOnAnimation(this); Loading Loading @@ -4151,7 +4161,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom; Math.max(mListPadding.bottom, mExtraScroll) : mListPadding.bottom; final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll; final int scrollBy = lastViewHeight - lastViewPixelsShowing + extraScroll; smoothScrollBy(scrollBy, mScrollDuration); smoothScrollBy(scrollBy, mScrollDuration, true); mLastSeenPos = lastPos; mLastSeenPos = lastPos; if (lastPos < mTargetPos) { if (lastPos < mTargetPos) { Loading Loading @@ -4182,14 +4192,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll); final int extraScroll = Math.max(mListPadding.bottom, mExtraScroll); if (nextPos < mBoundPos) { if (nextPos < mBoundPos) { smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll), smoothScrollBy(Math.max(0, nextViewHeight + nextViewTop - extraScroll), mScrollDuration); mScrollDuration, true); mLastSeenPos = nextPos; mLastSeenPos = nextPos; postOnAnimation(this); postOnAnimation(this); } else { } else { if (nextViewTop > extraScroll) { if (nextViewTop > extraScroll) { smoothScrollBy(nextViewTop - extraScroll, mScrollDuration); smoothScrollBy(nextViewTop - extraScroll, mScrollDuration, true); } } } } break; break; Loading @@ -4210,7 +4220,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = firstPos > 0 ? final int extraScroll = firstPos > 0 ? Math.max(mExtraScroll, mListPadding.top) : mListPadding.top; Math.max(mExtraScroll, mListPadding.top) : mListPadding.top; smoothScrollBy(firstViewTop - extraScroll, mScrollDuration); smoothScrollBy(firstViewTop - extraScroll, mScrollDuration, true); mLastSeenPos = firstPos; mLastSeenPos = firstPos; Loading @@ -4229,7 +4239,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te if (lastPos == mLastSeenPos) { if (lastPos == mLastSeenPos) { // No new views, let things keep going. // No new views, let things keep going. post(this); postOnAnimation(this); return; return; } } Loading @@ -4240,13 +4250,13 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final int extraScroll = Math.max(mListPadding.top, mExtraScroll); final int extraScroll = Math.max(mListPadding.top, mExtraScroll); mLastSeenPos = lastPos; mLastSeenPos = lastPos; if (lastPos > mBoundPos) { if (lastPos > mBoundPos) { smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration); smoothScrollBy(-(lastViewPixelsShowing - extraScroll), mScrollDuration, true); postOnAnimation(this); postOnAnimation(this); } else { } else { final int bottom = listHeight - extraScroll; final int bottom = listHeight - extraScroll; final int lastViewBottom = lastViewTop + lastViewHeight; final int lastViewBottom = lastViewTop + lastViewHeight; if (bottom > lastViewBottom) { if (bottom > lastViewBottom) { smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration); smoothScrollBy(-(bottom - lastViewBottom), mScrollDuration, true); } } } } break; break; Loading @@ -4255,7 +4265,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te case MOVE_OFFSET: { case MOVE_OFFSET: { if (mLastSeenPos == firstPos) { if (mLastSeenPos == firstPos) { // No new views, let things keep going. // No new views, let things keep going. post(this); postOnAnimation(this); return; return; } } Loading @@ -4277,17 +4287,22 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te final float modifier = Math.min(Math.abs(screenTravelCount), 1.f); final float modifier = Math.min(Math.abs(screenTravelCount), 1.f); if (position < firstPos) { if (position < firstPos) { smoothScrollBy((int) (-getHeight() * modifier), mScrollDuration); final int distance = (int) (-getHeight() * modifier); final int duration = (int) (mScrollDuration * modifier); smoothScrollBy(distance, duration, true); postOnAnimation(this); postOnAnimation(this); } else if (position > lastPos) { } else if (position > lastPos) { smoothScrollBy((int) (getHeight() * modifier), mScrollDuration); final int distance = (int) (getHeight() * modifier); final int duration = (int) (mScrollDuration * modifier); smoothScrollBy(distance, duration, true); postOnAnimation(this); postOnAnimation(this); } else { } else { // On-screen, just scroll. // On-screen, just scroll. final int targetTop = getChildAt(position - firstPos).getTop(); final int targetTop = getChildAt(position - firstPos).getTop(); final int distance = targetTop - mOffsetFromTop; final int distance = targetTop - mOffsetFromTop; smoothScrollBy(distance, final int duration = (int) (mScrollDuration * (int) (mScrollDuration * ((float) distance / getHeight()))); ((float) Math.abs(distance) / getHeight())); smoothScrollBy(distance, duration, true); } } break; break; } } Loading Loading @@ -4393,6 +4408,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te * @param duration Duration of the scroll animation in milliseconds. * @param duration Duration of the scroll animation in milliseconds. */ */ public void smoothScrollBy(int distance, int duration) { public void smoothScrollBy(int distance, int duration) { smoothScrollBy(distance, duration, false); } void smoothScrollBy(int distance, int duration, boolean linear) { if (mFlingRunnable == null) { if (mFlingRunnable == null) { mFlingRunnable = new FlingRunnable(); mFlingRunnable = new FlingRunnable(); } } Loading @@ -4414,7 +4433,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te } } } else { } else { reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); reportScrollStateChange(OnScrollListener.SCROLL_STATE_FLING); mFlingRunnable.startScroll(distance, duration); mFlingRunnable.startScroll(distance, duration, linear); } } } } Loading
core/java/android/widget/OverScroller.java +5 −1 Original line number Original line Diff line number Diff line Loading @@ -35,7 +35,7 @@ public class OverScroller { private final SplineOverScroller mScrollerX; private final SplineOverScroller mScrollerX; private final SplineOverScroller mScrollerY; private final SplineOverScroller mScrollerY; private final Interpolator mInterpolator; private Interpolator mInterpolator; private final boolean mFlywheel; private final boolean mFlywheel; Loading Loading @@ -113,6 +113,10 @@ public class OverScroller { this(context, interpolator, flywheel); this(context, interpolator, flywheel); } } void setInterpolator(Interpolator interpolator) { mInterpolator = interpolator; } /** /** * The amount of friction applied to flings. The default value * The amount of friction applied to flings. The default value * is {@link ViewConfiguration#getScrollFriction}. * is {@link ViewConfiguration#getScrollFriction}. Loading