美文网首页
Scroller原理

Scroller原理

作者: gczxbb | 来源:发表于2018-11-17 16:41 被阅读15次

Scroller类,改变mScrollX和mScrollY值,实现视图内部平缓偏移。View的scrollTo和scrollBy方法也可以改变Scroll值,但它们一瞬间完成,体验不好。ViewPager和ScrollView的自动滚动效果都是通过它实现的。本文介绍它的实现原理。


在视图内部定义一个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;//X方向开始位置
    mStartY = startY;//Y方向开始位置
    mFinalX = startX + dx;//X方向结束的位置
    mFinalY = startY + dy;//Y方向结束的位置
    mDeltaX = dx;//X方法偏移的距离
    mDeltaY = dy;//Y方向偏移的距离
    mDurationReciprocal = 1.0f / (float) mDuration;
}

该方法有五个参数,默认duration是250毫秒,startX和startY是开始位置,dx和dy是偏移量,mStartTime初始化起始时间。根据起始位置和偏移计算结束位置。

dy正值,内部视图整体向上移动。
dy负值,内部视图整体向下移动。

从上面源码可以看出,该方法仅仅是初始化,在Scroller对象记录一些的值而已。调用后一定要invalidate方法视图刷新。
实现滚动的视图重写View的computeScroll方法。在invalidate方法刷新时,会回调到该方法中。

@Override
public void computeScroll() {
    if (mScroller.computeScrollOffset()) {
        scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
        postInvalidate();//继续刷新UI。
    }
    super.computeScroll();
}

它在View类的源码中是空方法,视图渲染时触发,不重写无法实现滚动效果,Scroller的computeScrollOffset方法,计算Scroller当前偏移量。

public boolean computeScrollOffset() {
    if (mFinished) {//每次startScroll时,设置false。
        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;
            case FLING_MODE:
             //Fling效果
        }
    }
    else {
        mCurrX = mFinalX;
        mCurrY = mFinalY;
        mFinished = true;
    }
    return true;
}

如果滚动已经结束,退出该方法,根据起始时间和当前时间,以及速率控制拦截器,计算此刻应该所在的位置mCurrX和mCurrY。scrollTo方法,滚动到该位置,postInvalidate方法继续刷新。刷新中继续回调computeScroll方法。因此,实现在一定时间内平滑滚动一定距离。
如果已经到达持续时间,将当前位置设置成结束位置,mFinished结束标志,下一次computeScrollOffset方法直接返回,computeScroll方法将不再滚动和刷新。
逻辑和补间动画实现原理类似。


总结

Scroller原理比较简单,重写View基类的computeScroll方法。
startScroll方法后,一定要刷新视图,否则不会出现滚动效果。


任重而道远

相关文章

网友评论

      本文标题:Scroller原理

      本文链接:https://www.haomeiwen.com/subject/ynxifqtx.html