美文网首页
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