Scroller滑动剖析

Scroller

官方介绍:Scroller里面封装了滚动操作,并通过收集数据产生滚动动画

1.Scroller的使用

mScroller = new Scroller(context);
public void beginScroll(){
    mScroller.startScroll(0,0,-200,0,3000);
    invalidate();
}
public void computeScroll() {
    if (mScroller.computeScrollOffset()){
        scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
        postInvalidate();
    }
}

从实例代码来看,Scroller的使用非常简单,初始化一个Scroller对象,调用startScroll()方法并invalidate,然后重写computeScroll(),调用scrollTo()方法,并postInvalidate()
我们来看下实际运行效果:
Scroller滑动剖析_第1张图片
简单的几行代码就简单实现了弹性滑动的效果,我已经迫不及待想了解Scroller实现弹性滑动的原理。

2.Scroller弹性滑动原理分析

首先来看下startScroll()方法

  public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        mMode = SCROLL_MODE;
        mFinished = false;
        mDuration = duration;
        mStartTime = AnimationUtils.currentAnimationTimeMillis();
        mStartX = startX;
        mStartY = startY;
        mFinalX = startX + dx;
        mFinalY = startY + dy;
        mDeltaX = dx;
        mDeltaY = dy;
        mDurationReciprocal = 1.0f / (float) mDuration;
    }

可以看出Scroller收集了一系列的数据,包括开始坐标,偏移量,滚动时长,以当前时间作为startTime,并计算出最终坐标。
然后我们来看下computeScroll()方法

public void computeScroll() {
    if (mScroller.computeScrollOffset()){
        scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
        postInvalidate();
    }
}

computeScroll()方法中,我们先判断了Scroller是否滚动完毕,然后获取currXcurrY并作为参数传入到scrollTo()方法进行滚动操作,并调用postInvalidate()
我们继续看下computeScrollOffset是如何判断滚动是否结束?

 public boolean computeScrollOffset() {
    if (mFinished) {
        return false;
    }
    int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime);
    if (timePassed < mDuration) {
        switch (mMode) {
        case SCROLL_MODE:
            final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);
            mCurrX = mStartX + Math.round(x * mDeltaX);
            mCurrY = mStartY + Math.round(x * mDeltaY);
            break;
    }
    else {
        mCurrX = mFinalX;
        mCurrY = mFinalY;
        mFinished = true;
    }
    return true;
}

而在computeScrollOffset()方法中,我们通过当前时间和startScroll()方法中获取的startTime的时间差来计算得到currXcurrY,和属性动画里面的插值器原理类似。
computeScroll()调用了scrollTo进行瞬间滑动,而弹性滑动我们其实可以理解为连续的瞬间滑动,按照这种理解,computeScroll()应该每隔一段时间就调用,才会产生弹性滑动的效果,通过查看comuteScroll()方法的调用链,我们可以看出在draw方法里调用了computeScroll(),所以整个流程就很清楚了。
调用startScroll()方法,然后invalidate(),导致View重绘,同时darw()方法里面会调用computeScroll()方法,在computeScroll()方法中,我们首先判断是否滑动完毕,如果没有滑动完毕就计算currX,currY,并作为参数传入scrollTo方法中,然后调用postInvalidta()方法,而postInvalidate()也会导致view重绘,结果就进入到循环状态,直到滚动结束。

3.Scroller实现弹性滑动的流程

Scroller滑动剖析_第2张图片

你可能感兴趣的:(Scroller滑动剖析)