OverScroller 是 Scroller 的加強版,增加了滾出視圖范圍之后的回彈效果,但這個效果最好還是別用了。
OverScroller 是一個輔助類,用來實現(xiàn)視圖的平滑滾動。
說道平滑,實質(zhì)就是利用系統(tǒng)重畫的間隔,16ms(實際值),不斷重新計算值并重畫。無論是使用 ValueAnimator ,還是 OverScroller ,本質(zhì)都是一樣的。
平滑滾動

GIF.gif
滾動的實質(zhì)是移動了畫布的原點,所以視圖本身的坐標(biāo)和大小都沒發(fā)生變化,依舊能觸發(fā)點擊事件。
public class CustomLinearLayout extends LinearLayout {
// ... constructor
OverScroller scroller = new OverScroller(getContext());
public void smoothScroll() {
int increment = 200;
int duration = 300;
scroller.startScroll(0, getScrollY(), 0, increment, duration);
invalidate();
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(0, scroller.getCurrY());
}
}
}
case SCROLL_MODE:
// 這個時間是不可修改的
long time = AnimationUtils.currentAnimationTimeMillis();
final long elapsedTime = time - mScrollerX.mStartTime;
final int duration = mScrollerX.mDuration;
if (elapsedTime < duration) {
// 根據(jù)過去的時間計算滾動距離,線性插值器就是 Y=X,其他差值器也會經(jīng)過(0,0) 和(1,1),變的只是趨勢。
// q 是一個 0~1 的值。
final float q = mInterpolator.getInterpolation(elapsedTime / (float) duration);
mScrollerX.updateScroll(q);
mScrollerY.updateScroll(q);
} else {
abortAnimation();
}
break;
void updateScroll(float q) {
// 計算時使用的是 float ,精度高;最后的值是 int,因為像素是最小單位。
mCurrentPosition = mStart + Math.round(q * (mFinal - mStart));
}
fling
OverScroller 的另一個功能就是 fling。
平滑滾動是以過去時間到達 duration 作為滾動結(jié)束條件的。
fling 則是捕捉一個 fling 事件,獲取出初始速度(模擬滑動的慣性),然后設(shè)置一定的阻力,計算出速度消減為 0 所需的時間,作為 duration。
fling 的實現(xiàn)很復(fù)雜,需要物理和高數(shù)的知識(三次樣條差值),看不懂。