的实质和应用

Scroller简介
Android中组件的滑动主要是依赖Scroller类。

最常使用的是scrollTo/scrollBy方法

1.scrollTo(x,y):滚动到
2.scrollBy(dx,dy):滚动了
3.mScrollX=getScrollX()=>等于View左边缘和View内容左边缘在水平方向的距离

平滑滚动的原理
1.Scroller 类并不负责“滚动”这个动作,只是根据要滚动的起始位置和结束位置生成中间的过渡位置, 从而形成一个滚动的动画。
2.一个 View 的滚动不是自身发起的动作,而是由父容器驱动子组件来完成,换句话说需要Scroller和ViewGroup的配合才能产生滚动这个过程。所以,不要误以为是View自己在滚动显然不是,而是容器让子组件滚动,主动权在 ViewGroup 手中。
3.scrollTo和scrollBy只能改变View内容的位置,不能改变View在布局中的位置。
4.滚动往往分别两个阶段:第一个阶段是手指在屏幕上滑动,容器内的子组件跟随手指的速率一起滑动,当手指松开后, 进入第二个阶段——惯性滚动,滚动不会马上停止,而是给出一个负的加速度,滚动速度会越来越慢,直到最后处于静态状态。
自定义View常用办法
1) 调用 scroller 的 startScroll()方法定义滚动的起始位置,滚动的距离和时间等参数;
2) 通过 invalidate()或 postInvalidate()方法刷新,调用 draw(Canvas)方法重绘组件;
3) draw()方法里面调用 computeScroll()计算下一个位置的坐标;
4) computeScroll()中计算时间判断滑动时间是否结束,未结束时再次调用 invalidate()或 postInvalidate()方法刷新重绘:
5) 判断 computeScrollOffset()方法的返回值,如果为 false 表示结束滚动,为 true 表示继续滚动。
Scroller本身不能实现(控制)View的的滑动,它的主要功能是不停计算View"应该"到达哪个坐标,然后调用scrollTo滑动到该坐标点。 这个思想和值动画的做法很像,但它跟ValueAnimator有个明显的区别就是:它不会主动更新动画的值。
所以Scroller是完全可以脱离View来使用的。
看过一些优秀的自定义view的源码,有些作者是结合Scroller+Handler使用的。
例如,惯性滚动模式,常规方法,我们使用fling函数计算在一段时间内坐标点的变化过程,在computeScroll()函数中计算每一小段时间View的坐标然后进行相应的操作(可能是平移/旋转等),最后postInvalidate()导致onDraw()调用,重新计算和绘制直到结束。可见,invalidate()/postInvalidate()函数对于Scroller来说,它的作用只是回调computeScroll从而更新x和y的值而已.
基本如下:

draw
↓
onDraw
↓
computeScroll
↓
postInvalidate
↓
onDraw
↓
computeScroll
↓
...
↓
onDraw

Scroller如果要脱离View来使用,必须先脱离postInvalidate方法,那怎么定时刷新computeScroll方法呢,明白原理后其实很简单,这里是使用Handler,首先发送消息,接收消息时同样可以直接取到mScroller.getCurrY()和getCurrX(),然后做出相应的逻辑处理(平移/旋转等),接着重复发送消息,如此循环。
基本如下:

sendMessage
↓
handleMessage
↓
computeScroll
↓
sendMessage
↓
...
↓
computeScroll

一个简单的例子,对比DiskView和DiskHandlerView类