1. Scroller的官方api:
This class encapsulates scrolling. You can use scrollers (Scroller or OverScroller) to collect the data you need to produce a scrolling animation—for example, in response to a fling gesture.
大致意思:
这个类封装了滑动。您可以使用滚动条(Scroller或OverScroller)来收集产生滚动动画所需的数据,例如,响应一个手指动作。
2 先介绍一下实现View的滑动通过如下几种方式:
2.1 View自身的ScrollTo/ScrollBy方法,进行View的滑动
2.2 通过动画将View进行平移效果实现滑动
2.3 改变View的LayoutParams使View进行重新布局绘制是实现滑动
3 使用ScrollTo/ScrollBy实现View的滑动:
ScrollTo和ScrollBy都可以实现View的滑动,但是有什么区别?
3.1简单解释一下
scrollTo: 将自己的View滑动到(x,y)的位置,如果已在(x,y)的位置,则不会有任何滑动的效果
scrollBy: 将自己的View滑动相对于自己的(x,y)的位置,即使在(x,y)的位置,也会发生滑动,因为是相对于View本身
为什么要去解释这个方法的使用:因为在Scroller里面的方法中,使用的就是这两个方法。
4 接下来开始真正的解析Scroller的使用
以下是官方使用example:
private Scroller mScroller = new Scroller(context);
...
public void zoomIn() {
// Revert any animation currently in progress
mScroller.forceFinished(true);
// Start scrolling by providing a starting point and
// the distance to travel
mScroller.startScroll(0, 0, 100, 0);
// Invalidate to request a redraw
invalidate();
}
在看看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;
}
我们会发现startScroll()方法内部并没有实现相关的滑动的代码,那View是如何滑动的?你是否看见了当调用玩startScroll()方法后,执行了一行
// Invalidate to request a redraw
invalidate();
在invalidate()方法中会执行一系列的操作(测量绘制等),然后才会出现View的滑动
当然仅仅调用startScroll()方法是不会有弹性滑动的效果,也就是说有一个过渡动画。当然Google也提供了进行自定义滑动的弹性动画,通过重写computeScroll()方法进行实现:如下
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
}
也就是去计算滑动:scrollTo(mScroller.getCurrX(), mScroller.getCurrY());scrollTo()方法我们在上面已经介绍过了,那么mScroller.getCurrX()是什么鬼,我们继续看源码:
/**
* Returns the current X offset in the scroll.
* 返回滑动中的当前X的偏移量
* @return The new X offset as an absolute distance from the origin.
*/
public final int getCurrX() {
return mCurrX;
}
可以看到返回了一个 mCurrX对象,那么mCurrX是如何赋值的?
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;
}
就可以看出mCurrX 是根据时间差值和差值器综合计算出来的滑动的距离。到这里我们就会明白,只要computeScrollOffset()返回true ,即还没有滑动结束,则会一直调用scrollTo()和invalidate()方法,进行View的滑动。