美文网首页
Scroller 解析

Scroller 解析

作者: xingtangcunliu | 来源:发表于2016-05-24 16:49 被阅读0次

    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 解析

          本文链接:https://www.haomeiwen.com/subject/ywezrttx.html