欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Scroller简介

程序员文章站 2024-01-28 10:01:10
...

之前说的scrollTo和scrollBy确实可以实现View的滚动,但我们要想让View像我们常见的ViewPager那样平滑的滚动,只用这两方法是做不多的,因为它们产生的滚动是不连贯的,闪烁的,所以系统也为我们提供了Scroller这个类来实现View的平滑滚动

Scroller典型用法

Scroller mScroller = new Scroller(mContext);

private void smoothScroll(int destX, int destY) {
        int scrollX = getScrollX();
        int deltaX = destX - scrollX;
        mScroller.startScroll(scrollX, 0, deltaX, 0, 500);
        invalidate();
    }

@Override
    public void computeScroll() {
        super.computeScroll();
        if (mScroller.computeScrollOffset()) {
            scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
            invalidate();
        }
    }

根据上面的代码可把Scroller的使用概括为以下五个主要步骤

  1. 初始化Scroller
  2. 调用startScroll()开始滚动
  3. 执行invalidate()刷新界面
  4. 重写View的computeScroll()并在其内部实现与滚动相关的业务逻辑
  5. 再次执行invalidate()刷新界面

我们知道手机屏幕左上角为原点(0,0)

创建一些子View的时候,就会有一些超过屏幕的区域,可正可负,如图所示
Scroller简介

getScrollX():屏幕原点X坐标减去调用视图左上角X坐标,例如蓝色图得到的为0-(-480)=480

getScrollY():屏幕原点Y坐标减去调用视图左上角Y坐标,例如蓝色图得到的为0-0=0

mScroller.startScroll(int startX,int startY,int dx,int dy)

startX:表示View X坐标滚动的开始位置;
startY:表示View Y坐标滚动的开始位置 
dx:表示View 从X坐标的开始位置需要滚动的距离(这里dx的正负是和ScrllTo() 的x一样的)
dy:表示View 从Y坐标开始位置需要滚动的距离(dy的正负和scrllTo的 y 一样的)

startScroll源码

/**
   * Start scrolling by providing a starting point, the distance to travel,
   * and the duration of the scroll.
   * 
   * @param startX Starting horizontal scroll offset in pixels. Positive
   *        numbers will scroll the content to the left.
   * @param startY Starting vertical scroll offset in pixels. Positive numbers
   *        will scroll the content up.
   * @param dx Horizontal distance to travel. Positive numbers will scroll the
   *        content to the left.
   * @param dy Vertical distance to travel. Positive numbers will scroll the
   *        content up.
   * @param duration Duration of the scroll in milliseconds.
   */
  public void startScroll(int startX, int startY, int dx, int dy, int duration) {
      mMode = SCROLL_MODE;
      mFinished = false;
      mDuration = duration;
      mStartTime = AnimationUtils.currentAnimationTimeMillis();
      mStartX = startX;
      mStartY = startY;
      mFinalX = startX + dx;
      mFinalY = startY + dy;
      mDeltaX = dx;
      mDeltaY = dy;
      mDurationReciprocal = 1.0f / (float) mDuration;
  }

通过源码可以看到,当调用startScroll()时,内部并没有做什么滚动的操作,只是做了赋值的操作,所以当调用了这段代码之后,
我们需要调用invalidate()方法来让View重绘从而调用View里computeScroll()方法,在View源码里computeScroll()方法是个空实现,所以我们可以在这个方法里面做滚动的逻辑

例如:

public void computeScroll(){
    if (mScroller.computeScrollOffset()) {
        scrollTo(0, mScroller.getCurrY());
        postInvalidate();
    }
    super.computeScroll();
}

computeScroll()方法里,我们一般用mScroller.compuScrollOffset()来判断View的滚动是否在继续,返回true表示还在继续,false 表示结束

DEMO

Scroller简介

Demo下载地址

相关标签: scroller