Android scroll的封装器Scroller (三)

来源:互联网 发布:淘宝开店需要多少资金 编辑:程序博客网 时间:2024/06/05 16:13


实现View的滚动(滑动、动画)效果, 用到了Scroller,还要实现View类的computeScroll()方法:

/**     * Called by a parent to request that a child update its values for mScrollX     * and mScrollY if necessary. This will typically be done if the child is     * animating a scroll using a {@link android.widget.Scroller Scroller}     * object.     */    public void computeScroll() {    }

子类实现这个方法后, 怎么样被调用呢? 简单了解下: 每次调用View的invalidate()或postInvalidate()进行重绘, 就会调用到子View的draw()方法, draw()方法内调用了

computeScroll(),  在该方法内调用invalidate()或者postInvalidate()来触发界面重绘,

 重新绘制View又触发computeScroll(),所以就进入一个递归循环阶段,这样就实现在某个时间段里面滚动某段距离的一个平滑的滚动效果。

@Override     public void computeScroll() {          if (scroller.computeScrollOffset()) {               scrollTo(scroller.getCurrX(), 0);               invalidate();          }     }

具体流程图如下:

了解Scroller:

Scroller有三个构造方法,其中二、三可以使用动画插值器。除了构造方法外,Scroller还有以下几个重要方法:computeScrollOffset()、

startScroll(int startX, int startY, int dx, int dy, int duration)、

fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) 等。

 startScroll(int startX, int startY, int dx, int dy, int duration)从方法名字来看应该是滑动开始的地方,事实上我们在使用的时候也是先调用这个方法的,

它的作用是:(startX , startY)在duration时间内前进(dx,dy)个单位,即到达坐标为(startX+dx , startY+dy)    但是从源码来看,

/**     * Start scrolling by providing a starting point and the distance to travel.     *      * @param startX Starting horizontal scroll offset in pixels. Positive     *        numbers will scroll the content to the left.     * @param startY Starting vertical scroll offset in pixels. Positive numbers     *        will scroll the content up.     * @param dx Horizontal distance to travel. Positive numbers will scroll the     *        content to the left.     * @param dy Vertical distance to travel. Positive numbers will scroll the     *        content up.     * @param duration Duration of the scroll in milliseconds.     */    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;    }

这个方法更像是一个构造方法用来初始化赋值的,比如设置滚动模式、开始时间,持续时间、起始坐标、结束坐标等等,并没有任何对View的滚动操作,

当然还有一个重要的变量:mDurationReciprocal。因为这个变量要在接下来介绍的computeScrollOffset()方法使用,

computeScrollOffset()方法主要是根据当前已经消逝的时间来计算当前的坐标点,并且保存在mCurrX和mCurrY值中,那这个消逝的时间就是如何计算出来的呢?

之前在startScroll()方法的时候获取了当前的动画毫秒并赋值给了mStartTime,在computeScrollOffset()中再一次调用AnimationUtils.currentAnimationTimeMillis()

来获取动画毫秒减去mStartTime就是消逝时间了。然后进去if判断,如果动画持续时间小于设置的滚动持续时间mDuration,则是SCROLL_MODE,

再根据Interpolator来计算出在该时间段里面移动的距离,移动的距离是根据这个消逝时间乘以mDurationReciprocal,就得到一个相对偏移量,

再进行Math.round(x * mDeltaX)计算,就得到最后的偏移量,然后赋值给mCurrX, mCurrY,所以mCurrX、 mCurrY 的值也是一直变化的。

总结一下该方法的作用就是,计算在0到mDuration时间段内滚动的偏移量,并且判断滚动是否结束,true代表还没结束,false则表示滚动结束了。

Scroller的源码并不复杂,  对照源码, 理解更深入。


0 0