从源码的角度深入分析Scroller
转载须注明出处,谢谢!http://blog.csdn.net/chdjj
这篇文章我将从源码的角度深入分析Scroller类。在阅读的时候,建议大家打开源码对照着看,否则可能看的云里雾里。
一.Scroller的用途
熟悉android的同学必然对Scroller不陌生,Scroller是一个弹性滑动对象,可以制作很多酷炫的滑动效果,Lancher中的滑屏效果就有使用到Scroller。
我们知道,View类中的scrollTo和scrollBy方法提供了滑动操作,但是这种滑动操作是瞬间完成的,就是说你为scrollTo提供终点坐标,该方法只要一调用,我们就会发现已经滚动到目的地了,这种方式很显然用户体验是不好的,因而android工程师为我们封装了Scroller类,这个类可以为View带来缓慢移动的效果。
具体使用方式通常是通过在你自定义的View中调用Scroller的startScroll并刷新视图,另外需重写computeScroll方法(刷新视图过程中会调用此方法),在该方法中调用Scroller的computeScrollOffset计算应该滚动到的位置,然后使用scrollTo滚动到该位置,再调用invalidate刷新,就可以实现滚动效果了(不了解的同学建议先去熟悉Scroller用法)。
Scroller使用示例(代码片段):
[java] view plaincopy
- public class MyView extends LinearLayout
- {
- private Scroller mScroller;
- ... ...
- private void smoothScrollTo(int destX,int destY)
- {
- int scrollX = getScrollX();
- int scrollY = getScrollY();
- int deltaX = destX-scrollX;
- int deltaY = destY-scrollY;
- mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, 1000);
- invalidate();
- }
- @Override
- public void computeScroll()
- {
- if(mScroller != null)
- {
- if(mScroller.computeScrollOffset())
- {
- scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
- Log.d(TAG,"scrollX="+getScrollX()+",scrollY="+getScrollY());
- postInvalidate();
- }
- }
- }
- }
二.ScrollTo、ScrollBy、getScrollX、getScrollY方法分析
在分析Scroller源码之前,我们必须先了解ScrollTo,ScrollBy,getScrollX,getScrollY这几个方法的作用。这四个方法都是View类提供的,这点先明确。
我们先分析getScrollX和getScrollY方法,查看源码实现:
getScrollX和getScrollY方法返回的是mScrollX和mScrollY变量。这两个变量是什么呢?
这里我直接告诉大家,mScrollX和mScrollY指的是视图内容相对于视图原始起始坐标的偏移量,mScrollX和mScrollY的默认值为0,因为默认是没有偏移的。另外需注意偏移量的正负问题,因为是相对视图起始坐标的,所以如果你是向右偏移那么mScrollX应该是负数,而向左偏移mScrollX为正数。再举个例子,比如你定义了一个ImageView,其左上角的坐标为(100,80),此时mScrollX和mScrollY值都为0(没有偏移),现在你要把该ImageView移到(120,100)处,也就是右下方,那么你的mScrollX应该是100-120=-20,mScrollY应该是80-100=-20,这下你该明白了吧。
明白了这个问题,scrollBy和scrollTo也就不在话下了,我们查看源码:
[java] view plaincopy
- public void scrollTo(int x, int y) {
- if (mScrollX != x || mScrollY != y) {
- int oldX = mScrollX;
- int oldY = mScrollY;
- mScrollX = x;
- mScrollY = y;
- invalidateParentCaches();
- onScrollChanged(mScrollX, mScrollY, oldX, oldY);
- if (!awakenScrollBars()) {
- postInvalidateOnAnimation();
- }
- }
- }
- public void scrollBy(int x, int y) {
- scrollTo(mScrollX + x, mScrollY + y);
- }
先看scrollTo方法,它首先判断x,y方向的偏移量(即mScrollX,mScrollY)是否和传进来的偏移量(即x,y)相同,如果相同那么直接返回,否则我们将更新mScrollX和mScrollY,并且通知界面发生改变请求重绘。通过这种方式就可以实现滚动效果了,只是是瞬间移动的。再看这个scrollBy,直接调用的是scrollTo,根据参数很容易发现,这个方法的作用是在当前偏移基础上,再继续偏移(x,y)单位。需要注意的是这两个方法的参数是偏移量而不是实际位置哦!
这里还有一点需要注意,那就是你调用一个View的scrollTo方法进行滚动时,滚动的并不是该View本身,而是该View的内容。比如你要对一个Button进行滚动的话,应该在Button外面包一个ViewGroup,然后调用ViewGroup的scrollTo方法。这一点也很重要,大家需要注意下!
Tag:
Freenovo 发表于2014-12-03 23:31:00 | 编辑 | 分享 0
引用地址:
posted on 2014-12-03 23:31 Freedom000 阅读(160) 评论(0) 编辑 收藏 举报