Scroller 解析

Scroller 只是简单的滑动辅助类,记录滑动的距离、时间等信息。

public void startScroll(int startX, int startY, int dx, int dy, int duration) {   
      // 滑动模式分为平滑的滑动SCROLL_MODE模式,惯性滑动FLING_MODE模式
       mMode = SCROLL_MODE;   
      //是否结束
       mFinished = false;  
      // 滑动持续时间 ,如果不设置默认250ms
       mDuration = duration;  
      //滑动开始时间  
       mStartTime = AnimationUtils.currentAnimationTimeMillis();
       //滑动x初始值
       mStartX = startX;  
      //滑动y初始值 
       mStartY = startY;    
       //x最终值
       mFinalX = startX + dx;   
       //y最终值
       mFinalY = startY + dy;    
      //x改变值
       mDeltaX = dx;  
      //y改变值  
       mDeltaY = dy; 
      //单位时间比          
       mDurationReciprocal = 1.0f / (float) mDuration;
}

从这个方法可以看出只是简单的属性记录而已,没有直接对view进行操作。所以要view调用自己的重绘方法,postInvalidate();或Invalidate()
让view刷新从而调用computeScroll()方法。
我们都知道computeScroll方法一般都是如下写:

public void computeScroll() {   
        //判断有没有滑动结束
        if (mScroller.computeScrollOffset()) {        
             if (mScroller.getCurrX() == mScroller.getFinalX()) {          
                   countMoveEnd();       
             } else {            
                  int xPosition = mScroller.getCurrX();           
                  mMove += (mLast - xPosition);           
                  changeMoveAndValue();           
                  mLast = xPosition;        
            }    
      }
}

关键就在mScroller.computeScrollOffset()上,该方法实现对滑动距离数据的改变。

public boolean computeScrollOffset() {    
      //判断是否结束,结束反射false
      if (mFinished) {        
           return false;    
      }   
     //获取已经滑动的时间,当前时间减去开始时间
      int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() - mStartTime); 
      //已经滑动时间是否小于设置滑动总时间   
      if (timePassed < mDuration) {        
         switch (mMode) {        
         case SCROLL_MODE:    
         //根据Interpolator插值器计算在该时间段里移动的距离加上初始赋值赋值给mCurrX和mCurrY        
              final float x = mInterpolator.getInterpolation(timePassed * mDurationReciprocal);            
             mCurrX = mStartX + Math.round(x * mDeltaX);                                    
             mCurrY = mStartY + Math.round(x * mDeltaY);            
             break;     
        //滑动时,抬起手执行的惯性运动,通过复杂的运算获取当前的mCurrX 、mCurrY 值。
         case FLING_MODE:            
             final float t = (float) timePassed / mDuration;            
             final int index = (int) (NB_SAMPLES * t);            
             float distanceCoef = 1.f;            
             float velocityCoef = 0.f;            
             if (index < NB_SAMPLES) {                
                   final float t_inf = (float) index / NB_SAMPLES; 
                   final float t_sup = (float) (index + 1) / NB_SAMPLES;                
                   final float d_inf = SPLINE_POSITION[index];
                   final float d_sup = SPLINE_POSITION[index + 1];
                   velocityCoef = (d_sup - d_inf) / (t_sup - t_inf);
                   distanceCoef = d_inf + (t - t_inf) * velocityCoef; 
             }                       
             mCurrVelocity = velocityCoef * mDistance / mDuration * 1000.0f;                        
             mCurrX = mStartX + Math.round(distanceCoef * (mFinalX - mStartX));            
            // Pin to mMinX <= mCurrX <= mMaxX            
            mCurrX = Math.min(mCurrX, mMaxX);            
            mCurrX = Math.max(mCurrX, mMinX);
            mCurrY = mStartY + Math.round(distanceCoef * (mFinalY - mStartY));            
           // Pin to mMinY <= mCurrY <= mMaxY            
            mCurrY = Math.min(mCurrY, mMaxY);            
            mCurrY = Math.max(mCurrY, mMinY);            
            if (mCurrX == mFinalX && mCurrY == mFinalY) { 
                   mFinished = true;            
            }            
           break;       
            }    
       }  else {     
            //如果时间到达设定时间结束。   
            mCurrX = mFinalX;        
            mCurrY = mFinalY;        
            mFinished = true;   
       }   
    return true;
}

如上面的computeScroll方法所述,调用mScroller.computeScrollOffset()修改mCurrY 以及mCurrY 的属性,然后再获取mScroller.getCurrX()的值,进行操作,其中changeMoveAndValue方法中含有postInvalidate()方法,重新绘制页面进而又调用computeScroll方法,直到mScroller.computeScrollOffset()返回false。

你可能感兴趣的:(Scroller 解析)