这篇文章我将从源码的角度深入分析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 plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)
    <div>
    </div>
  </div>
</div>


  - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout  </span>
  
  - <span style="color: black;">{  </span>
  
  - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> Scroller mScroller;  </span>
  
  - <span style="color: black;">    &#8230; &#8230;   </span>
  
  - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> smoothScrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destX,<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destY)  </span>
  
  - <span style="color: black;">    {  </span>
  
  - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollX = getScrollX();  </span>
  
  - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollY = getScrollY();  </span>
  
  - <span style="color: black;">  </span>
  
  - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaX = destX-scrollX;  </span>
  
  - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaY = destY-scrollY;  </span>
  
  - <span style="color: black;">        mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, <span class="number" style="color: #c00000;">1000</span>);  </span>
  
  - <span style="color: black;">        invalidate();  </span>
  
  - <span style="color: black;">    }  </span>
  
  - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
  
  - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll()  </span>
  
  - <span style="color: black;">    {  </span>
  
  - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>)  </span>
  
  - <span style="color: black;">        {  </span>
  
  - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller.computeScrollOffset())  </span>
  
  - <span style="color: black;">            {  </span>
  
  - <span style="color: black;">                scrollTo(mScroller.getCurrX(),mScroller.getCurrY());  </span>
  
  - <span style="color: black;">                Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+getScrollX()+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+getScrollY());  </span>
  
  - <span style="color: black;">                postInvalidate();  </span>
  
  - <span style="color: black;">            }  </span>
  
  - <span style="color: black;">        }  </span>
  
  - <span style="color: black;">    }  </span>
  
  - <span style="color: black;">      </span>
  
  - <span style="color: black;">      </span>
  
  - <span style="color: black;">}  </span>
**二.ScrollTo、ScrollBy、getScrollX、getScrollY方法分析**
** **
在分析Scroller源码之前,我们必须先了解ScrollTo,ScrollBy,getScrollX,getScrollY这几个方法的作用。这四个方法都是View类提供的,这点先明确。
我们先分析getScrollX和getScrollY方法,查看源码实现:
**[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)
      <div>
      </div>
    </div>
  </div>
  
  
    - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * Return the scrolled left position of this view. This is the left edge of</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * the displayed part of your view. You do not need to draw any pixels</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * farther left, since those are outside of the frame of your view on</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * screen.</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     *</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * @return The left edge of the displayed part of your view, in pixels.</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     */</span>  </span>
    
    - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> getScrollX() {  </span>
    
    - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">return</span> mScrollX;  </span>
    
    - <span style="color: black;">    }  </span>
    
    - <span style="color: black;">    <span class="comment" style="color: #008200;">/**</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * Return the scrolled top position of this view. This is the top edge of</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * the displayed part of your view. You do not need to draw any pixels above</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * it, since those are outside of the frame of your view on screen.</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     *</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     * @return The top edge of the displayed part of your view, in pixels.</span> </span>
    
    - <span style="color: black;"><span class="comment" style="color: #008200;">     */</span>  </span>
    
    - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> getScrollY() {  </span>
    
    - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">return</span> mScrollY;  </span>
    
    - <span style="color: black;">    }  </span>
    
  
</div>

<div>
  <div>
    getScrollX和getScrollY方法返回的是mScrollX和mScrollY变量。这两个变量是什么呢?
  </div>
  
  <div>
  </div>
  
  <div>
    这里我直接告诉大家,**mScrollX和mScrollY指的是视图内容相对于视图原始起始坐标的偏移量**,mScrollX和mScrollY的默认值为0,因为默认是没有偏移的。另外需注意偏移量的正负问题,因为是相对视图起始坐标的,所以如果你是**向右偏移那么mScrollX应该是负数,而向左偏移mScrollX为正数**。再举个例子,比如你定义了一个ImageView,其左上角的坐标为(100,80),此时mScrollX和mScrollY值都为0(没有偏移),现在你要把该ImageView移到(120,100)处,也就是右下方,那么你的mScrollX应该是100-120=-20,mScrollY应该是80-100=-20,这下你该明白了吧。
  </div>
</div>

<div>
  明白了这个问题,scrollBy和scrollTo也就不在话下了,我们查看源码:
</div>

<div>
</div>

<div class="dp-highlighter bg_java">
  <div class="bar">
    <div class="tools" style="color: silver;">
      **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

      
      <div>
      </div>
    </div>
  </div>
  
  
    - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> scrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> x, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> y) {  </span>
    
    - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScrollX != x || mScrollY != y) {  </span>
    
    - <span style="color: black;">           <span class="keyword" style="font-weight: bold; color: #006699;">int</span> oldX = mScrollX;  </span>
    
    - <span style="color: black;">           <span class="keyword" style="font-weight: bold; color: #006699;">int</span> oldY = mScrollY;  </span>
    
    - <span style="color: black;">           mScrollX = x;  </span>
    
    - <span style="color: black;">           mScrollY = y;  </span>
    
    - <span style="color: black;">           invalidateParentCaches();  </span>
    
    - <span style="color: black;">           onScrollChanged(mScrollX, mScrollY, oldX, oldY);  </span>
    
    - <span style="color: black;">           <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!awakenScrollBars()) {  </span>
    
    - <span style="color: black;">               postInvalidateOnAnimation();  </span>
    
    - <span style="color: black;">           }  </span>
    
    - <span style="color: black;">       }  </span>
    
    - <span style="color: black;">   }  </span>
    
    - <span style="color: black;">  </span>
    
    - <span style="color: black;">   <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> scrollBy(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> x, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> y) {  </span>
    
    - <span style="color: black;">       scrollTo(mScrollX + x, mScrollY + y);  </span>
    
    - <span style="color: black;">   }  </span>
    
  
</div>

<div>
  先看scrollTo方法,它首先判断x,y方向的偏移量(即mScrollX,mScrollY)是否和传进来的偏移量(即x,y)相同,如果相同那么直接返回,否则我们将更新mScrollX和mScrollY,并且通知界面发生改变请求重绘。通过这种方式就可以实现滚动效果了,只是是瞬间移动的。再看这个scrollBy,直接调用的是scrollTo,根据参数很容易发现,这个方法的作用是在当前偏移基础上,再继续偏移(x,y)单位。需要注意的是这两个方法的**参数是偏移量而不是实际位置**哦!
</div>

<div>
</div>

<div>
  这里还有一点需要注意,那就是你**调用一个View的scrollTo方法进行滚动时,滚动的并不是该View本身,而是该View的内容。**比如你要对一个Button进行滚动的话,应该在Button外面包一个ViewGroup,然后调用ViewGroup的scrollTo方法。这一点也很重要,大家需要注意下!
</div>

<div>
</div>

<div>
  **三.Scroller源码分析**
</div>

<div>
  ** **
</div>

<div>
  Scroller的精华在于computeScrollOffset和startScroll方法,所以我们重点分析这两个方法。
</div>

<div>
  分析之前,先看这个类中定义的一些变量:
</div>

<div class="dp-highlighter bg_java">
  <div class="bar">
    <div class="tools" style="color: silver;">
      **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

      
      <div>
      </div>
    </div>
  </div>
  
  
    - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mMode;<span class="comment" style="color: #008200;">//模式,有SCROLL_MODE和FLING_MODE</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mStartX;<span class="comment" style="color: #008200;">//起始x方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mStartY;<span class="comment" style="color: #008200;">//起始y方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mFinalX;<span class="comment" style="color: #008200;">//终点x方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mFinalY;<span class="comment" style="color: #008200;">//终点y方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mCurrX;<span class="comment" style="color: #008200;">//当前x方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mCurrY;<span class="comment" style="color: #008200;">//当前y方向偏移</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">long</span> mStartTime;<span class="comment" style="color: #008200;">//起始时间</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> mDuration;<span class="comment" style="color: #008200;">//滚动持续时间</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDurationReciprocal;<span class="comment" style="color: #008200;">//持续时间的倒数</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDeltaX;<span class="comment" style="color: #008200;">//x方向应该滚动的距离,mDeltaX=mFinalX-mStartX</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> mDeltaY;<span class="comment" style="color: #008200;">//y方向应该滚动的距离,mDeltaY=mFinalY-mStartY</span>  </span>
    
    - <span style="color: black;">  <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> mFinished;<span class="comment" style="color: #008200;">//是否结束</span>  </span>
    
  
</div>



  对这些变量有个大致印象之后,我们就开始看startScroll源码了:
**[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)
      <div>
      </div>
    </div>
  </div>
  
  
    - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> startScroll(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> startX, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> startY, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dx, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dy) {  </span>
    
    - <span style="color: black;">        startScroll(startX, startY, dx, dy, DEFAULT_DURATION);  </span>
    
    - <span style="color: black;">    }  </span>
    
    - <span style="color: black;">  </span>
    
    - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> startScroll(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> startX, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> startY, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dx, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> dy, <span class="keyword" style="font-weight: bold; color: #006699;">int</span> duration) {  </span>
    
    - <span style="color: black;">        mMode = SCROLL_MODE;  </span>
    
    - <span style="color: black;">        mFinished = <span class="keyword" style="font-weight: bold; color: #006699;">false</span>;  </span>
    
    - <span style="color: black;">        mDuration = duration;  </span>
    
    - <span style="color: black;">        mStartTime = AnimationUtils.currentAnimationTimeMillis();  </span>
    
    - <span style="color: black;">        mStartX = startX;  </span>
    
    - <span style="color: black;">        mStartY = startY;  </span>
    
    - <span style="color: black;">        mFinalX = startX + dx;  </span>
    
    - <span style="color: black;">        mFinalY = startY + dy;  </span>
    
    - <span style="color: black;">        mDeltaX = dx;  </span>
    
    - <span style="color: black;">        mDeltaY = dy;  </span>
    
    - <span style="color: black;">        mDurationReciprocal = <span class="number" style="color: #c00000;">1</span>.0f / (<span class="keyword" style="font-weight: bold; color: #006699;">float</span>) mDuration;  </span>
    
    - <span style="color: black;">    }  </span>
    
  
</div>

<div>
  这个所谓的startScroll方法里面全部是对上面那些变量赋值的,比如将当前模式置为SCROLL_MODE,设置持续时间,起点终点偏移,起始时间等等。这个方法似乎并没有触发start scroll,恩,的确是这样的。那么到底怎么触发scroll呢?我们将这个问题留到下一个部分分析。
</div>

<div>
  为了让大家理解这些变量的作用,我画了一张图。
</div>



  ![](http://img.blog.csdn.net/20141202145628031?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)</div> 
  
  <div>
    <div>
      解释下,图中我们假设从A点滚动到B点,那么,**如果知道mStartX,mStartY(由startScroll的startX和startY参数得到)和mDeltaX,mDeltaY(由startScroll的dx和dy参数得到)。那么,mFinalX和mFinalY就很容易得到了。此外在加上duration持续时间,那么我们就可以根据(当前时间-mStartTime)占duration的比例来算出当前位置,也即mCurrX和mCurrY。**我不会告诉你,这就是computeScrollOffset的作用!通过上面分析我们发现,**startScroll方法其实相当于一个预处理,为computeScrollOffset提供数据。**
    </div>
    
    <div>
    </div>
    
    <div>
      下面我们查看computeScrollOffset源码:
    </div>
    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> computeScrollOffset() {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mFinished) {  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">false</span>;  </span>
        
        - <span style="color: black;">        }  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">int</span> timePassed = (<span class="keyword" style="font-weight: bold; color: #006699;">int</span>)(AnimationUtils.currentAnimationTimeMillis() &#8211; mStartTime);  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (timePassed < mDuration) {  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">switch</span> (mMode) {  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">case</span> SCROLL_MODE:  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">float</span> x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);  </span>
        
        - <span style="color: black;">                mCurrX = mStartX + Math.round(x * mDeltaX);  </span>
        
        - <span style="color: black;">                mCurrY = mStartY + Math.round(x * mDeltaY);  </span>
        
        - <span style="color: black;">                <span class="keyword" style="font-weight: bold; color: #006699;">break</span>;  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">case</span> FLING_MODE:  </span>
        
        - <span style="color: black;">                 &#8230; &#8230;  </span>
        
        - <span style="color: black;">                <span class="keyword" style="font-weight: bold; color: #006699;">break</span>;  </span>
        
        - <span style="color: black;">            }  </span>
        
        - <span style="color: black;">        }  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">else</span> {  </span>
        
        - <span style="color: black;">            mCurrX = mFinalX;  </span>
        
        - <span style="color: black;">            mCurrY = mFinalY;  </span>
        
        - <span style="color: black;">            mFinished = <span class="keyword" style="font-weight: bold; color: #006699;">true</span>;  </span>
        
        - <span style="color: black;">        }  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">true</span>;  </span>
        
        - <span style="color: black;">    }  </span>
        
      
    </div>
    
    <div>
      看,是不是很好理解了。**首先判断是否结束(mFinished==true?),如果没有结束,那么程序继续向下跑,计算timePassed,即当前时间减去开始时间,如果小于mDuration,那么就可以根据比例计算出当前位置,当然了,这里使用了Interpolator来控制动画的效果,加速或者减速等等。如果已经超过了mDuration了,那么滚动应该停止了,所以将mFinished置为ture,下次调用computeScrollOffset就会返回false了。**
    </div>
    
    <div>
      ** **
    </div>
    
    <div>
      到这里,我们把Scroller中的重要部分都分析完了,但是我们发现这两个方法都没有涉及具体滚动。那么滚动到底是如何触发的呢?下面我们将对整个流程进行源码分析。
    </div>
    
    <div>
    </div>
    
    <div>
      **四.滚动流程分析**
    </div>
    
    <div>
      ** **
    </div>
    
    <div>
      在第一部分中,我给出了一个Scroller的使用示例,在smoothScrollTo方法中我们调用了Scroller的startScroll,然后调用了invalidate方法刷新视图,这个滚动效果就是由invalidate触发的!我们知道,调用了invalidate方法将会引起整个view系统的重绘,所以我们得从View的绘制说起。有经验的同学都应该知道,View的绘制包括三个主要过程,分别是measure,layout和draw。下面我们看View类的draw方法源码:
    </div>
    
    <div>
    </div>
    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas) {  </span>
        
        - <span style="color: black;">         &#8230; &#8230;  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">/*</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        * Draw traversal performs several drawing steps which must be executed</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        * in the appropriate order:</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      1. Draw the background</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      2. If necessary, save the canvas&#8217; layers to prepare for fading</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      3. Draw view&#8217;s content</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      4. Draw children</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      5. If necessary, draw the fading edges and restore layers</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        *      6. Draw decorations (scrollbars for instance)</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">        */</span>  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">// Step 1, draw the background, if needed</span>  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">int</span> saveCount;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!dirtyOpaque) {  </span>
        
        - <span style="color: black;">           drawBackground(canvas);  </span>
        
        - <span style="color: black;">       }  </span>
        
        - <span style="color: black;">         &#8230; &#8230;  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">// Step 2, save the canvas&#8217; layers</span>  </span>
        
        - <span style="color: black;">         &#8230; &#8230;  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">// Step 3, draw the content</span>  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!dirtyOpaque) onDraw(canvas);  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">// Step 4, draw the children</span>  </span>
        
        - <span style="color: black;">       dispatchDraw(canvas);  </span>
        
        - <span style="color: black;">       <span class="comment" style="color: #008200;">// Step 5, draw the fade effect and restore layers</span>  </span>
        
        - <span style="color: black;">         &#8230; &#8230;  </span>
        
        - <span style="color: black;">   }  </span>
        
      
    </div>
    
    

      draw方法将绘制分成了六步,其中第三步是调用onDraw去绘制内容,第四步是调用dispatchDraw去绘制子视图。我们看下dispatchDraw方法:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">    * Called by draw to draw the child views. This may be overridden</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">    * by derived classes to gain control just before its children are drawn</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">    * (but after its own view has been drawn).</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">    * @param canvas the canvas on which to draw the view</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">    */</span>  </span>
        
        - <span style="color: black;">   <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas) {  </span>
        
        - <span style="color: black;">   }  </span>
        
      
    </div>
    
    

      恩,没错,是个空方法,因为只有ViewGroup才有子视图,所以我们来到ViewGroup中,找到dispatchDraw:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas) {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> usingRenderNodeProperties = canvas.isRecordingFor(mRenderNode);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> childrenCount = mChildrenCount;  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">final</span> View[] children = mChildren;  </span>
        
        - <span style="color: black;">         &#8230; &#8230;  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">for</span> (<span class="keyword" style="font-weight: bold; color: #006699;">int</span> i = <span class="number" style="color: #c00000;"></span>; i < childrenCount; i++) {  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">int</span> childIndex = customOrder ? getChildDrawingOrder(childrenCount, i) : i;  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">final</span> View child = (preorderedList == <span class="keyword" style="font-weight: bold; color: #006699;">null</span>)  </span>
        
        - <span style="color: black;">                    ? children[childIndex] : preorderedList.get(childIndex);  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">if</span> ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) {  </span>
        
        - <span style="color: black;">                more |= drawChild(canvas, child, drawingTime);  </span>
        
        - <span style="color: black;">            }  </span>
        
        - <span style="color: black;">        }    </span>
        
        - <span style="color: black;">    }  </span>
        
      
    </div>
    
    

      代码也是极其长的,这里截取了一部分。我们看到这个方法中调用了drawChild方法,从名字上就可以看出这个方法是用来绘制子视图的,找到其实现:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> drawChild(Canvas canvas, View child, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime) {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">return</span> child.draw(canvas, <span class="keyword" style="font-weight: bold; color: #006699;">this</span>, drawingTime);  </span>
        
        - <span style="color: black;">    }  </span>
        
      
    </div>
    
    

      这里调用了view的draw方法,当然,这个draw方法跟上面那个draw不一样,因为它有三个参数!那还等什么,我们回到View的代码中找到这个含有三个参数的draw方法:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> draw(Canvas canvas, ViewGroup parent, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime) {  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> more = <span class="keyword" style="font-weight: bold; color: #006699;">false</span>;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> childHasIdentityMatrix = hasIdentityMatrix();  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">final</span> <span class="keyword" style="font-weight: bold; color: #006699;">int</span> flags = parent.mGroupFlags;  </span>
        
        - <span style="color: black;">       &#8230; &#8230;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">int</span> sx = <span class="number" style="color: #c00000;"></span>;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">int</span> sy = <span class="number" style="color: #c00000;"></span>;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (!hasDisplayList) {  </span>
        
        - <span style="color: black;">           computeScroll();<span class="comment" style="color: #008200;">//终于找到了computeScroll</span>  </span>
        
        - <span style="color: black;">           sx = mScrollX;  </span>
        
        - <span style="color: black;">           sy = mScrollY;  </span>
        
        - <span style="color: black;">       }  </span>
        
        - <span style="color: black;">        &#8230; &#8230;  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">return</span> more;  </span>
        
        - <span style="color: black;">   }  </span>
        
      
    </div>
    
    <div>
      在其中,我们找到了computeScroll方法!当然View中的computeScroll方法是空的,需要我们根据场景自己复写。
    </div>
    
    <div>
      比如,我发现,TextView中就有复写这个方法:
    </div>
    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">   <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll() {  </span>
        
        - <span style="color: black;">       <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>) {  </span>
        
        - <span style="color: black;">           <span class="keyword" style="font-weight: bold; color: #006699;">if</span> (mScroller.computeScrollOffset()) {  </span>
        
        - <span style="color: black;">               mScrollX = mScroller.getCurrX();  </span>
        
        - <span style="color: black;">               mScrollY = mScroller.getCurrY();  </span>
        
        - <span style="color: black;">               invalidateParentCaches();  </span>
        
        - <span style="color: black;">               postInvalidate();  <span class="comment" style="color: #008200;">// So we draw again</span>  </span>
        
        - <span style="color: black;">           }  </span>
        
        - <span style="color: black;">       }  </span>
        
        - <span style="color: black;">   }  </span>
        
      
    </div>
    
    <div>
      好了,折腾了这么久,**<span style="color: #000080;">下面我们再回顾下这个过程:我们在自定义view中调用了startScroll方法为滚动设置了一些基本数据,然后通过invalidate由上而下刷新view视图,首先是根视图(通常是ViewGroup)的draw方法被调用,然后调用onDraw绘制视图内容,接着dispatchDraw方法被调用去绘制子视图,dispatchDraw方法会对每个子视图调用drawChild方法,而drawChild方法会调用该子View的draw方法(三个参数),在draw方法中会调用computeScroll方法进行滚动,而computeScroll方法是被复写的,视场景而定,通常是根据computeScrollOffset来判断是否需要滑动,如果需要的话,接着调用postInvalidate再由上至下重新绘制,如此一来便实现了平滑滚动的效果!</span>**
    </div>
    
    <div>
      ok,到这里总算是把Scroller讲清楚了!
    </div>
    
    <div>
    </div>
    
    <div>
      **五.实例分析**
    </div>
    
    <div>
      ** **
    </div>
    
    <div>
      为了便于理解,我这里写了一个小例子,通过打印日志的形式让大家理解上面所讲的内容。
    </div>
    
    <div>
      首先是几个自定义的view:
    </div>
    
    <div>
    </div>
    
    <div>
      MyLinearLayout:
    </div>
    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.LinearLayout;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyLinearLayout <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout  </span>
        
        - <span style="color: black;">{  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>;  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyLinearLayout(Context context)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyLinearLayout(Context context, AttributeSet attrs)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>draw&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.draw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>onDraw&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll()  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG, <span class="string" style="color: blue;">&#8220;MyLinearLayout&#8212;>computeScroll&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.computeScroll();  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">}  </span>
        
      
    </div>
    
    

      MyView(实现了平滑滚动效果):
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.LinearLayout;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.Scroller;  </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;">/**</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;"> * @author Rowandjj</span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;"> * </span> </span>
        
        - <span style="color: black;"><span class="comment" style="color: #008200;"> */</span>  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> LinearLayout  </span>
        
        - <span style="color: black;">{  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>;  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> Scroller mScroller;  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyView(Context context)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context);  </span>
        
        - <span style="color: black;">        init();  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyView(Context context, AttributeSet attrs)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs);  </span>
        
        - <span style="color: black;">        init();  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> init()  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        mScroller = <span class="keyword" style="font-weight: bold; color: #006699;">new</span> Scroller(getContext());   </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> testSmoothScroll()  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="comment" style="color: #008200;">//向右下方平滑滚动(向右偏移100,向下偏移100)</span>  </span>
        
        - <span style="color: black;">        smoothScrollTo(-<span class="number" style="color: #c00000;">100</span>,-<span class="number" style="color: #c00000;">100</span>);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> smoothScrollTo(<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destX,<span class="keyword" style="font-weight: bold; color: #006699;">int</span> destY)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollX = getScrollX();  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> scrollY = getScrollY();  </span>
        
        - <span style="color: black;">        Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+scrollX+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+scrollY);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaX = destX-scrollX;  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">int</span> deltaY = destY-scrollY;  </span>
        
        - <span style="color: black;">        mScroller.startScroll(scrollX,scrollY,deltaX, deltaY, <span class="number" style="color: #c00000;">1000</span>);  </span>
        
        - <span style="color: black;">        invalidate();  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> draw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>draw run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.draw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>onDraw run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> dispatchDraw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>dispatchDraw run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.dispatchDraw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">boolean</span> drawChild(Canvas canvas, View child, <span class="keyword" style="font-weight: bold; color: #006699;">long</span> drawingTime)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>drawChild run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">return</span> <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.drawChild(canvas, child, drawingTime);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll()  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;MyView&#8212;&#8212;>computeScroll run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller != <span class="keyword" style="font-weight: bold; color: #006699;">null</span>)  </span>
        
        - <span style="color: black;">        {  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">if</span>(mScroller.computeScrollOffset())  </span>
        
        - <span style="color: black;">            {  </span>
        
        - <span style="color: black;">                scrollTo(mScroller.getCurrX(),mScroller.getCurrY());  </span>
        
        - <span style="color: black;">                Log.d(TAG,<span class="string" style="color: blue;">&#8220;scrollX=&#8221;</span>+getScrollX()+<span class="string" style="color: blue;">&#8220;,scrollY=&#8221;</span>+getScrollY());  </span>
        
        - <span style="color: black;">                postInvalidate();  </span>
        
        - <span style="color: black;">            }  </span>
        
        - <span style="color: black;">        }  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">}  </span>
        
      
    </div>
    
    

      MyImageView:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.content.Context;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.graphics.Canvas;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.AttributeSet;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.util.Log;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.widget.ImageView;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MyImageView <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> ImageView  </span>
        
        - <span style="color: black;">{  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> <span class="keyword" style="font-weight: bold; color: #006699;">static</span> <span class="keyword" style="font-weight: bold; color: #006699;">final</span> String TAG = <span class="string" style="color: blue;">&#8220;TEST&#8221;</span>;  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyImageView(Context context)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> MyImageView(Context context, AttributeSet attrs)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>(context, attrs);  </span>
        
        - <span style="color: black;">    }     </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onDraw(Canvas canvas)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;myImageView&#8212;->onDraw run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onDraw(canvas);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> computeScroll()  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        Log.i(TAG,<span class="string" style="color: blue;">&#8220;myImageView&#8212;->computeScroll run&#8221;</span>);  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.computeScroll();  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">}  </span>
        
      
    </div>
    
    <div>
      我们根据上面三个自定义view做一个布局,外层是MyLinearLayout,中间是MyView,最里面是一个MyImageView.
    </div>
    
    <div>
      activity_main.xml:
    </div>
    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><LinearLayout xmlns:android=<span class="string" style="color: blue;">&#8220;http://schemas.android.com/apk/res/android&#8221;</span>  </span>
        
        - <span style="color: black;">    android:layout_width=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span>  </span>
        
        - <span style="color: black;">    android:layout_height=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span>  </span>
        
        - <span style="color: black;">    android:orientation=<span class="string" style="color: blue;">&#8220;vertical&#8221;</span> >  </span>
        
        - <span style="color: black;">    <com.example.scrollerdemo.MyLinearLayout  </span>
        
        - <span style="color: black;">        xmlns:tools=<span class="string" style="color: blue;">&#8220;http://schemas.android.com/tools&#8221;</span>  </span>
        
        - <span style="color: black;">        android:layout_width=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span>  </span>
        
        - <span style="color: black;">        android:layout_height=<span class="string" style="color: blue;">&#8220;match_parent&#8221;</span>  </span>
        
        - <span style="color: black;">        android:background=<span class="string" style="color: blue;">&#8220;#ffaaff&#8221;</span>  </span>
        
        - <span style="color: black;">        tools:context=<span class="string" style="color: blue;">&#8220;com.example.scrollerdemo.MainActivity&#8221;</span> >  </span>
        
        - <span style="color: black;">        <com.example.scrollerdemo.MyView  </span>
        
        - <span style="color: black;">            android:id=<span class="string" style="color: blue;">&#8220;@+id/mv&#8221;</span>  </span>
        
        - <span style="color: black;">            android:layout_width=<span class="string" style="color: blue;">&#8220;200dp&#8221;</span>  </span>
        
        - <span style="color: black;">            android:layout_height=<span class="string" style="color: blue;">&#8220;200dp&#8221;</span>  </span>
        
        - <span style="color: black;">            android:layout_marginLeft=<span class="string" style="color: blue;">&#8220;50dp&#8221;</span>  </span>
        
        - <span style="color: black;">            android:layout_marginTop=<span class="string" style="color: blue;">&#8220;100dp&#8221;</span>  </span>
        
        - <span style="color: black;">            android:background=<span class="string" style="color: blue;">&#8220;@android:color/darker_gray&#8221;</span>  </span>
        
        - <span style="color: black;">            android:orientation=<span class="string" style="color: blue;">&#8220;vertical&#8221;</span> >  </span>
        
        - <span style="color: black;">            <com.example.scrollerdemo.MyImageView  </span>
        
        - <span style="color: black;">                android:layout_width=<span class="string" style="color: blue;">&#8220;wrap_content&#8221;</span>  </span>
        
        - <span style="color: black;">                android:layout_height=<span class="string" style="color: blue;">&#8220;wrap_content&#8221;</span>  </span>
        
        - <span style="color: black;">                android:src=<span class="string" style="color: blue;">&#8220;@drawable/ic_launcher&#8221;</span> />  </span>
        
        - <span style="color: black;">        </com.example.scrollerdemo.MyView>  </span>
        
        - <span style="color: black;">    </com.example.scrollerdemo.MyLinearLayout>  </span>
        
        - <span style="color: black;"></LinearLayout>  </span>
        
      
    </div>
    
    

      下面是MainActivity的代码:
    

    
    <div class="dp-highlighter bg_java">
      <div class="bar">
        <div class="tools" style="color: silver;">
          **[java]** [view plain](http://blog.csdn.net/chdjj/article/details/41678897#)[copy](http://blog.csdn.net/chdjj/article/details/41678897#)[![在CODE上查看代码片](https://code.csdn.net/assets/CODE_ico.png)](https://code.csdn.net/snippets/539577)[![派生到我的代码片](https://code.csdn.net/assets/ico_fork.svg)](https://code.csdn.net/snippets/539577/fork)

          
          <div>
          </div>
        </div>
      </div>
      
      
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">package</span> com.example.scrollerdemo;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.app.Activity;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.os.Bundle;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">import</span> android.view.View.OnClickListener;  </span>
        
        - <span style="color: black;"><span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">class</span> MainActivity <span class="keyword" style="font-weight: bold; color: #006699;">extends</span> Activity <span class="keyword" style="font-weight: bold; color: #006699;">implements</span> OnClickListener  </span>
        
        - <span style="color: black;">{  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">private</span> MyView mv = <span class="keyword" style="font-weight: bold; color: #006699;">null</span>;  </span>
        
        - <span style="color: black;">      </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">protected</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onCreate(Bundle savedInstanceState)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">super</span>.onCreate(savedInstanceState);  </span>
        
        - <span style="color: black;">        setContentView(R.layout.activity_main);  </span>
        
        - <span style="color: black;">          </span>
        
        - <span style="color: black;">        mv = (MyView) findViewById(R.id.mv);  </span>
        
        - <span style="color: black;">        mv.setOnClickListener(<span class="keyword" style="font-weight: bold; color: #006699;">this</span>);  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">    <span class="annotation" style="color: #646464;">@Override</span>  </span>
        
        - <span style="color: black;">    <span class="keyword" style="font-weight: bold; color: #006699;">public</span> <span class="keyword" style="font-weight: bold; color: #006699;">void</span> onClick(View v)  </span>
        
        - <span style="color: black;">    {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">switch</span> (v.getId())  </span>
        
        - <span style="color: black;">        {  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">case</span> R.id.mv:<span class="comment" style="color: #008200;">//点击时触发滚动效果</span>  </span>
        
        - <span style="color: black;">            mv.testSmoothScroll();  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">break</span>;  </span>
        
        - <span style="color: black;">        <span class="keyword" style="font-weight: bold; color: #006699;">default</span>:  </span>
        
        - <span style="color: black;">            <span class="keyword" style="font-weight: bold; color: #006699;">break</span>;  </span>
        
        - <span style="color: black;">        }  </span>
        
        - <span style="color: black;">    }  </span>
        
        - <span style="color: black;">}  </span>
        
      
    </div>
    
    

      代码很简单,不必过多介绍,下面看显示效果:
    

  </div>
  
  <div>
    ![](http://img.blog.csdn.net/20141202145938259?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)

打开logcat查看日志:

  <div>
    ![](http://img.blog.csdn.net/20141202150038428?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
  </div>
  
  <div>
  </div>
  
  <div>
    <div>
      这是第一次绘制,跟上面分析过程一致,首先是MyLinearLayout的draw和onDraw方法被调用,然后通过dispatchDraw绘制孩子,所以MyView的computeScroll、draw、onDraw、dispatchDraw等方法被调用,接着MyImageView的computeScroll和onDraw方法会被调用,如此从上到下进行一次绘制。
    </div>
    
    <div>
    </div>
    
    <div>
      下面我们点击安卓机器人图标,会调用testSmoothScroll方法,机器人会从左上角平滑滚动到右下角,此时我们查看logcat日志:
    </div>
    
    <div>
    </div>
    
    

      ![](http://img.blog.csdn.net/20141202150108521?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
    

    
    

      中间日志太多,省略了,下面这段是最后打印的
    

  </div>
  
  <div>
    ![](http://img.blog.csdn.net/20141202150226187?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY2hkamo=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)

    
    <div>
      通过日志可以看出,上面分析是正确的,通过在MyView的computeScroll方法中调用postInvalidate,导致不断重绘,直到偏移量达到startScroll事先指定的(-100,-100)。
    </div>
    
    <div>
    </div>
    
    <div>
      至此,本篇文章结束,希望对大家有所帮助!
    </div>
    
    <div>
      转自:http://blog.csdn.net/chdjj/article/details/41678897
    </div>
  </div></div>

💬 评论