Scroller源码更详细的分析见另一篇博客从源码的角度深入分析Scroller
Scoller类是系统提供的一个高级滚动辅助类 系统自带的scrollTo和scrollBy滚动方法都是瞬间滚动~即直接移动到某位置,瞬移! 而有时候我们需要个平滑的滚动,有过程的滚动,甚至滚动结束后还有个惯性逐渐减速的滚动~ 即跑到某个位置,我们可以看到从起点到终点的过程 而实现这种"有过程"的滚动~就需要用到Scroller类了 可以撸个代码,参考ScrollView类的scrollTo和smoothScrollTo方法的区别理解下带"过程"是怎么样的~ 但Scroller只是用于跟踪控件滑动的轨迹,此类不会移动控件,只相当于一个滚动轨迹记录工具所以需要你在View的一个回调函数computerScroll()中使用Scroller对象获取滑动的数据, 最后还是用scrollTo/By方法来实际控制某个View的滚动行为 比如下面的简化版smoothScroll方法
// 调用此方法滚动到目标位置
public void smoothScrollTo( int fx, int fy) {
int dx = fx - mScroller.getFinalX();
int dy = fy - mScroller.getFinalY();
smoothScrollBy (dx, dy);
}
// 调用此方法设置滚动的相对偏移
public void smoothScrollBy( int dx, int dy) {
// 设置mScroller的滚动偏移量
mScroller.startScroll( mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
// 这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
invalidate();
}
Scroller提供的除startScroll外,还有fling等有过程的移动方法,
查看Scroller源码会发现,方法中只会记录数值currentX/Y finalX/Y等等~
即只相当于轨迹记录作用
而实际移动则需要在view中的computScroll方法里处理,如下
@Override
public void computeScroll() {
// 先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset()) {
// 这里调用View的scrollTo()完成实际的滚动
scrollTo( mScroller.getCurrX(), mScroller .getCurrY());
// 必须调用该方法,否则不一定能看到滚动效果
invalidate();
}
super.computeScroll();
}
mScroller.computeScrollOffset方法是判断滚动过程是否完成的, 如果没有完成则需要不停的scrollTo到新目标位置~ 所以在if最末需要加一个invalidate(),该方法会再次触发computScroll,直到判断滚动已经完成为止 相当于一个while循环~ 判断mScroller余下的滚动是否还有未完成的部分, 是的话则滚动到Scroller计算的currentX/Y,然后invalidate刷新页面~ invalidate的时候又会触发computeScroll方法,然后继续判断 直到判断滚动完全完成了,则结束~ |
转自http://www.eoeandroid.com/thread-553376-1-1.html