进阶篇:站在源码的肩膀上全解Scroller工作机制 基础会了在看这个~吧,大神写得。感觉这个比较深一点
郭霖大神关于scroller 和我一样是萌新的话,可以先看看下面写的笔记,再看进阶篇大神们写的东西
以下是学习《进阶之光》的笔记哈
scrollTo 和 scrollBy 的区别:
scrollTo是移动到一个具体的坐标,相对于(0,0)坐标的位置。而scrollBy是表示移动的增量,相对于上一次坐标的位置。(上一次坐标的位置不一定是(0,0)。
注意:"scrollTo和scrollBy移动的是view的内容,如果是在viewgroup中使用,移动的是所有的子view"-----------------------就是说要移动某个view,就需要使用它的父view调用scrollTo或者scrollBy。
eg:((View)getParent()).scrollTo(-400,0); 这句话就是调用父view,使自身这个view向右水平移动400。
scrollTo(int x,int y)的参数 x值为负,向右移动,为正,向左移动。y为负向下,为正向上。scrollBy同理. 注意了:坐标是控件在手机屏幕显示的位置,而且移动的是手机屏幕!!
思路:假设我们面前有一块画布,上面有很多控件,我们需要通过一盏灯照亮才能看到,能够理解的是,不管我们怎么移动灯,画布上的东西是不会改变位置的。scrollTo改变的就是那盏灯的位置。灯光所照亮的地方是有限的。但是灯光没照亮的地方,画布上的东西依然存在。
这里比如一个imageView控件 在灯光中(手机屏幕) 的位置是(100,100),当调用scrollby(50,50)的时候,移动的是灯光!灯光向右移动50,向下移动50,但是iamgeView的位置在画布中的位置是不会改变的,灯光向右下角移动了,相当于imageView向左上角移动了。
自己画的加深理解~黑色圆是灯光初始位置,此时iamgeView在灯光中的位置坐标是(100,100),当时调用scrollBy(50,50)的时候,灯光向右移动50,向下移动50,移动后就是黄色的圈。此时iamgeView在黄色圈中的坐标是(50,50)。相对于灯光的位置,iamgeView向上移动50,向左移动50. 萌新有点啰嗦~说半天就在说怎么理解向右是负的,向左是正的。
scroller
scrollTo和scrollBy的移动都是一瞬间完成的,没有滑动的过程,使用scroller就可以拥有滑动过程。但是scroller本身没有实现滑动,滑动的实现原理:调用scrollTo的滑动,每滑动一小段距离就重绘一次,看起来就像是滑动了~~~^_^
使用:
1.创建scroller对象 scroller = new Scroller(Context);
2.重写computeScroll方法
3.调用startScroll。
最后在xml文件调用view:
在java代码里面调用:
完成
源码分析:
scroller构造方法有3个,第二个需要传入插值器,不传入就是用默认。
startScroll方法主要保存一些参数:
mMode会在computeScrollOffset中使用,mDurationReciprocal是时间的比例,1/ 时间长度,由源码可以看出里面并没有开启滑动或者动画的方法。真正的“滑动”在invalidate()调用重绘制view,在draw中调用computeScroll方法。所以我们重写这个方法。上面有图了。
computeScroll方法里面思路:判断当前滑动动画是否停止,没有停止就获取当前坐标,调用scrollTo,然后重新绘制。那么如何获取当前坐标,
源码中getCurrX返回的是mCurrX,y同理。进入computeScrollOffset方法,:
timePassed为当前时间减去动画刚刚开始的时间,就是动画已经执行的时间。如果时间小于动画执行的时间,switch判断模式,在startScroll中设置了模式,进入SCROLL_MODE,x是插值器的返回值,动画已执行时间乘以mDeltaX,(x轴总移动差值),就是动画执行的时间内x轴的位移量,加上初始位置,就是当前的x坐标。y同理。这里的mCurrx和mCurrY就是当前的坐标位置,调用getCurrX()方法返回的就是mCurrX。
大概就是这样。每隔一个时间段重新获取当前的位置,然后scrollTo去回绘制。不断重复就形成了动画。
网友评论