系统自带的scrollTo和scrollBy滚动方法都是瞬间滚动~即直接移动到某位置,瞬移!
而有时候我们需要个平滑的滚动,有过程的滚动,甚至滚动结束后还有个惯性逐渐减速的滚动~
即跑到某个位置,我们可以看到从起点到终点的过程~
而实现这种"有过程"的滚动~就需要用到Scroller类了
可以撸个代码,参考ScrollView类的scrollTo和smoothScrollTo方法的区别~
所以需要你在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等有过程的移动方法,
但是查看源码会发现,方法中只会记录数值currentX/Y finalX/Y等等~
即只相当于轨迹记录作用
而实际移动则需要再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方法,然后继续判断
直到判断滚动完全完成了,则结束~