从源码的角度深入分析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在CO<wbr>DE上查看代码片派生到我的代码片

  1. public class MyView extends LinearLayout  
  2. {  
  3.     private Scroller mScroller;  
  4.     ... ...   
  5.     private void smoothScrollTo(int destX,int destY)  
  6.     {  
  7.         int scrollX = getScrollX();  
  8.         int scrollY = getScrollY();  
  9.   
  10.         int deltaX = destX-scrollX;  
  11.         int deltaY = destY-scrollY;  
  12.         mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, 1000);  
  13.         invalidate();  
  14.     }  
  15.     @Override  
  16.     public void computeScroll()  
  17.     {  
  18.         if(mScroller != null)  
  19.         {  
  20.             if(mScroller.computeScrollOffset())  
  21.             {  
  22.                 scrollTo(mScroller.getCurrX(),mScroller.getCurrY());  
  23.                 Log.d(TAG,"scrollX="+getScrollX()+",scrollY="+getScrollY());  
  24.                 postInvalidate();  
  25.             }  
  26.         }  
  27.     }  
  28.       
  29.       
  30. }  

二.ScrollTo、ScrollBy、getScrollX、getScrollY方法分析

 

在分析Scroller源码之前,我们必须先了解ScrollTo,ScrollBy,getScrollX,getScrollY这几个方法的作用。这四个方法都是View类提供的,这点先明确。

我们先分析getScrollX和getScrollY方法,查看源码实现:

  

  •     public final int getScrollY() {  
  •         return mScrollY;  
  •     }  
  • 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在CO<wbr>DE上查看代码片派生到我的代码片

    1. public void scrollTo(int x, int y) {  
    2.        if (mScrollX != x || mScrollY != y) {  
    3.            int oldX = mScrollX;  
    4.            int oldY = mScrollY;  
    5.            mScrollX = x;  
    6.            mScrollY = y;  
    7.            invalidateParentCaches();  
    8.            onScrollChanged(mScrollX, mScrollY, oldX, oldY);  
    9.            if (!awakenScrollBars()) {  
    10.                postInvalidateOnAnimation();  
    11.            }  
    12.        }  
    13.    }  
    14.   
    15.    public void scrollBy(int x, int y) {  
    16.        scrollTo(mScrollX + x, mScrollY + y);  
    17.    }  

    先看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

    引用地址:

    原文地址:https://www.cnblogs.com/freenovo/p/4469764.html