Scroller相关

scrollTo/scrollBy

  • 这两个方法都是View的内部方法
  • scrollTo和scrollBy只能改变View的内容而不能改变View在布局中的位置。
  • 移动方向与笛卡尔坐标轴左右上下是相反的
  • 在滑动过程中,View内部的两个属性mscrollX和mscrollY都可以通过getScrollX和getScrollY方法获得,mscrollX就是View左边缘和View内容左边缘在水平方向的距离。同理,mscrollY就是View上边缘和View内容的上边缘的竖直方向的距离

Scroller

  • Scroller就是一个辅助类, 用来帮助进行弹性滑动。具体使用方法如下:
//在需要改动的view中
Scroller scroller = new Scroller(mContext);

//缓慢滚动到指定位置
private void smoothScrollTo(int destX, int destY){
      int scrollX = getScrollX();       //获取当前的mscrollX
      int scrolloY = getScrollY();     //获取当前的mscrollY
      int deltaX = destX - scrollX;
      int deltaY = destY - scrollY;
      mScroller.startScroll(scrollX, scrollY , deltaX, deltaY,1000);
      invalidate();
}


@override
public void computeScroll(){
      if ( mScroller.computeScrolljOffset()){
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            postInvalidate();
      }
}

上面的代码就是如何在自定义的View中添加弹性滑动的效果。在自定义的View初始化时,定义一个Scroller,然后自己添加一个private void smoothScrollTo()这样一个私有方法,用来被调用来执行滑动效果的。public void computeScroll()方法在view中本是一个空实现的方法,这个方法在view重绘时,draw方法中会被调用。那上面的代码整个逻辑流程是什么呢?让我们继续往下看。

  • Scroller的源码学习
    smoothScrollTo(int destX, int destY)方法中,整个逻辑流程如下:
  1. 我们首先利用view的getScrollX方法和getScrollY方法获取到现在view与其内容的偏移距离,
  2. 接着根据目标偏移距离和当前偏移距离的差值,得到这次目前需要进行得分位移
  3. 执行mScroller.startScroll()方法,输入参数是当前X,Y方向的偏移距离,目标的偏移距离,位移时间。下面介绍下mScroller.startScroll()方法的源码。主要功能是保存传递的几个参数。
public void startScroll(int startX, int startY,int dx,int dy,int duration){
     mMode = SCROLL_MODE;
     mFinished = false;
     mDurarion = duration;
     mStartTime = AnimationUtilesd.currentAnimationTimeMilllis();
     mStartX = startX;
     mStartY = startY;
     mFinalX = startX + dx;
     mFinalY = startY  + dy;
     mDeltaX = dx;
     mDeltaY = dy;
     mDurationReciprocal = 1.0f /(float) mDuration; 
}
  1. 调用invalidate()会导致该View重绘,View在draw()方法中会调用computeScroll()方法。
  2. computeScroll()方法,先调用mScroller.computeScrollOffset()方法,并判断其返回值。该方法的主要功能就是根据开始的坐标位移,目的坐标位移,当前的时间,总时间来确定此时此刻的位移X Y应该是多少,并赋给mCurrX和mCurrY。
    public boolean computeScrollOffset(){
          ...
          int timePassed = (int) (AnimationUtils.currentAnimationTimeMills() - mStartTime);
          
          if (timePassed < mDuration) {
                switch(mMode) {
                case SCROLL_MODE:
                      final float x = mInterpolartor.getInterpolation(timePassed * mDurationReciprocal);
                      mCurrX = mStartX + Math.round(x * mDeltaX);
                      mCurrY = mStartY + Math.round(x * mDeltaY);
                      break;
                      ......
                }
          }
          return true;         
    }
    
  3. computeScrollOffset()执行完后,在computeScroll方法中,使用scrollTo方法位移到刚刚计算出的mCurrX,mCurrY的位置上,然后调用postInvalidate()方法,再次要求重绘,再次调用draw方法,从而再次执行computeScroll( )方法让,从而能够绘制出不同时间在不同位置出现的移动画面。
    scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
    postInvalidate();
    

你可能感兴趣的:(Scroller相关)