专栏名称: 程序员大咖
为程序员提供最优质的博文、最精彩的讨论、最实用的开发资源;提供最新最全的编程学习资料:PHP、Objective-C、Java、Swift、C/C++函数库、.NET Framework类库、J2SE API等等。并不定期奉送各种福利。
目录
相关文章推荐
码农翻身  ·  Excel终于要完蛋了吗? ·  4 小时前  
蚂蚁技术AntTech  ·  论文秀Live#21 ICSE 2025 ... ·  18 小时前  
京东科技技术说  ·  【银河麒麟高级服务器操作系统】正式上线云主机 ... ·  4 天前  
京东科技技术说  ·  JDK从8升级到21的问题集 ·  3 天前  
51好读  ›  专栏  ›  程序员大咖

站在源码的肩膀上全解Scroller工作机制

程序员大咖  · 公众号  · 程序员  · 2018-01-05 10:24

正文

请到「今天看啥」查看全文



关于mScrollX,官方文档描述如下:




关于mScrollY,官方文档描述如下:



mScrollX和mScrollY用于描述View的内容在水平方向或垂直方向滚动的距离。


什么是View的内容呢?比如,对于一个TextView而言,文本就是它的内容;对于一个ViewGroup而言,子View就是它的内容。


故在此,我们请务必注意:scrollTo()和scrollBy()滚动的是View的内容,而不是将View做整体的移动。


嗯哼,继续看scrollBy()的源码:




哇哈,看到了吧:scrollBy()的源码非常简洁,它仅仅是再次调用了scrollTo()。


直白地说:它只是把输入参数x,y累加到了mScrollX和mScrollY上而已。


所以,scrollBy()方法是在mScrollX和mScrollY的基础上滚动的。


小结:


  1. mScrollX和mScrollY分别表示View在X、Y方向的滚动距离。

  2. scrollTo( )表示View相对于其初始位置滚动某段距离。
    由于View的初始位置是不变的,所以如果利用相同输入参数多次调用scrollTo()方法,View只会出现一次滚动的效果而不是多次。

  3. scrollBy( )表示在mScrollX和mScrollY的基础上继续滚动。


现在,已经对这两个方法有了基本的了解,我们再看看它们的用法。




在这个示例中对TextView分别调用scrollTo( )和scrollBy( ),代码如下:




当我们调用scrollBy()时,TextView的中的文本逐渐往其左侧滚动,当执行scrollTo()时TextView的中的文本会滚动到其右侧。嗯哼,在这是不是又印证了我们刚才的描述呢:执行scrollTo()和scrollBy()后View的内容发生了滚动,但是View本身是没有发生移动的。关于这点已经得到了验证,但是View的内容滚动的方向怎么和我们预想的不一样呢?平常我们不是说坐标是左负右正,上负下正么,为什么这里执行mTextView.scrollBy(30,0)时TextView的文本却是往X的负轴移动呢?


其实,许多人都是有类似的疑问,现在我们一起来探究其产生的原因。


在scrollTo()的源码中我们看到,该方法最后会调用postInvalidateOnAnimation()对View进行重绘从而执行到invalidate()。在此以Android 6.0 API Level 23为例,对其进行剖析:




嗯哼,看到第4行代码的时候,是不是就恍然大悟了呢?


在进行重绘的时候在会利用l - scrollX, t - scrollY, r - scrollX, b - scrollY计算出新的l,t,r,b。


如果在调用scrollTo()和scrollBy()时传入的x,y为正值,那么新的l,t,r,b均会变小,从而导致View的内容向左且向上滚动。


如果在调用scrollTo()和scrollBy()时传入的x,y为负值,那么新的l,t,r,b均会变大,从而导致View的内容向右且向下滚动。


刚才我们通过scrollTo()和scrollBy()作用于某个View,如果要想让多个View同时发生滚动,可以怎么办呢?很简单,只需要把这些View放到同一个ViewGroup中然后再调用这两个方法即可,例如mLinearLayout.scrollBy(50, 0)、mLinearLayout.scrollTo(100, 20)







请到「今天看啥」查看全文