android scroller

来源:互联网 发布:淘宝没销量怎么办 编辑:程序博客网 时间:2024/05/18 21:49

一、scrollTo与scrollBy的区别

 

(1)scrollTo的源码

   /**

    * Set the scrolled position of your view. This will cause a call to

    * {@link #onScrollChanged(int, int, int, int)} and the view will be

    * invalidated.

    * @param x the x position to scroll to

    * @param y the y position to scroll to

    */

   public void scrollTo(int x, int y) {

             //偏移位置发生了改变

       if (mScrollX != x || mScrollY != y) {

           int oldX = mScrollX;

           int oldY = mScrollY;

           mScrollX = x; //赋新值,保存当前便宜量

            mScrollY = y;

           //回调onScrollChanged方法

           onScrollChanged(mScrollX, mScrollY, oldX, oldY);

           if (!awakenScrollBars()) {

                invalidate();  //一般都引起重绘

           }

       }

}

(2)scrollBy的源码

  /**

    * Move the scrolled position of your view. This will cause a call to

    * {@link #onScrollChanged(int, int, int, int)} and the view will be

    * invalidated.

    * @param x the amount of pixels to scroll by horizontally

    * @param y the amount of pixels to scroll by vertically

    */

     public void scrollBy(int x, int y) {

       scrollTo(mScrollX + x, mScrollY + y);

    }

 (3) 区别


如上图所示,(1)为初始的可视区域,(2)为经scrollTo(x,y)后由(1)转换至,(3)为经scrollBy(a,b)由(2)转换至。(1),(2),(3)为屏幕上显示的内容。

(1)可视图:mScrollX=0,mScrollY=0;

(2)可视图scrollTo(x,y):mScrollX=x,mScrollY=y;

(3)可视图scrollBy(a,b):mScrollX=mScrollX+a=a+x,mScrollY=mScrollY+b=b+y;

 

 

一、Scroller类

Scroller类部分源码:

public class Scroller  {

   private int mStartX;    //起始坐标点 ,  X轴方向

   private int mStartY;    //起始坐标点 ,  Y轴方向

   private int mCurrX;     //当前坐标点  X轴, 即调用startScroll函数后,经过一定时间所达到的值

   private int mCurrY;     //当前坐标点  Y轴, 即调用startScroll函数后,经过一定时间所达到的值

  

   private float mDeltaX;  //应该继续滑动的距离, X轴方向

   private float mDeltaY;  //应该继续滑动的距离, Y轴方向

   private boolean mFinished;  //是否已经完成本次滑动操作, 如果完成则为 true

 

   //构造函数

   public Scroller(Context context) {

       this(context, null);

    }

   public final boolean isFinished() {

       return mFinished;

    }

   //强制结束本次滑屏操作

   public final void forceFinished(boolean finished) {

       mFinished = finished;

    }

   public final int getCurrX() {

       return mCurrX;

    }

    /* Call this when you want to know the new location.  If it returns true,

    * the animation is not yet finished. loc will be altered to provide the

    * new location. */ 

   //根据当前已经消逝的时间计算当前的坐标点,保存在mCurrX和mCurrY值中

   public boolean computeScrollOffset() {

       if (mFinished) {  //已经完成了本次动画控制,直接返回为false

           return false;

       }

       int timePassed = (int)(AnimationUtils.currentAnimationTimeMillis() -mStartTime);

       if (timePassed < mDuration) {

           switch (mMode) {

           case SCROLL_MODE:

                float x = (float)timePassed *mDurationReciprocal;

                ...

                mCurrX = mStartX + Math.round(x* mDeltaX);

                mCurrY = mStartY + Math.round(x* mDeltaY);

                break;

           ...

       }

       else {

           mCurrX = mFinalX;

           mCurrY = mFinalY;

           mFinished = true;

       }

       return true;

    }

   //开始一个动画控制,由(startX , startY)在duration时间内前进(dx,dy)个单位,即到达坐标为(startX+dx , startY+dy)出

   public void startScroll(int startX, intstartY, int dx, int dy, int duration) {

       mFinished = false;

       mDuration = duration;

       mStartTime = AnimationUtils.currentAnimationTimeMillis();

       mStartX = startX;       mStartY =startY;

       mFinalX = startX + dx;  mFinalY =startY + dy;

       mDeltaX = dx;            mDeltaY =dy;

       ...

    }

}

代码中比较重要的是computeScrollOffset与startScroll两个方法,startScroll是初始化数据,computeScrollOffset是计算出当前的坐标点mCurrX和mCuurY。(代码已注释的很详细)

 

 

二、View类中computeScroll调用

computeScroll源码:

/**

    * Called by a parent to request that a child update its values formScrollX

    * and mScrollY if necessary. This will typically be done if the child is

    * animating a scroll using a {@link android.widget.Scroller Scroller}

    * object.

    */由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制

    public void computeScroll() { //空方法 ,自定义ViewGroup必须实现方法体

    }

 

为了实现偏移控制,在view或者是ViewGroup中重载该方法。

其调用过程位于view的绘制流程draw()过程中

   @Override

   protected void dispatchDraw(Canvas canvas){

             ...

            

       for (int i = 0; i < count; i++) {

           final View child = children[getChildDrawingOrder(count, i)];

           if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE ||child.getAnimation() != null) {

                more |=drawChild(canvas, child, drawingTime);

           }

       }

    }

   protected boolean drawChild(Canvas canvas, View child, long drawingTime){

             ...

             child.computeScroll();

             ...

}


0 0
原创粉丝点击