Android Scroller初探

Android的滑动可以借助scrollTo()和scrollBy()来实现,scrollTo是以控件原始的位置作为参考,而scrollBy是以控件当前位置作为参考来滚动。而使用scrollTo和scrollBy来滑动控件,你会发现中间没有任何平滑滚动的效果,控件会直接滚动到目标位置,而系统中像ListView或者是ViewPager等,滑动都是比较平滑的,而他们的内部实现,就是借助于Scroller这个类来实现,下面就看看怎么来实现一个简单的ViewPager,从而到达我们想要的效果。


1. Scroller的作用

当我们给定一个滑动的起始位置和滑动的终止位置,scrollTo和scrollBy会直接瞬移到达,而scroller,则会根据两个位置的距离,给一个固定时间,来计算每次滑动多少,从而使滑动有一个时间差,实现滑动的平稳。
Scroller主要有下面几个方法:

/**
* Start scrolling by providing a starting point and the distance to travel.
* 根据用户提供的开始位置和距离进行滑动
* The scroll will use the default value of 250 milliseconds for the duration.
* 系统默认设置250毫秒的滑动时间
* @param startX Starting horizontal scroll offset in pixels. Positive numbers will scroll the content to the left.
* 参数startX 水平方向开始的位置
*        
* @param startY Starting vertical scroll offset in pixels. Positive numbers will scroll the content up.
*参数startY 垂直方向开始的位置        
* @param dx Horizontal distance to travel. Positive numbers will scroll the content to the left.
*参数dx 水平方向要滑动的距离        
* @param dy Vertical distance to travel. Positive numbers will scroll the content up.
* 参数 dy 垂直方向要滑动的距离       
*/
public void startScroll(int startX, int startY, int dx, int dy) {
   startScroll(startX, startY, dx, dy, DEFAULT_DURATION);
}

/**
     * Call this when you want to know the new location.  If it returns true,
     * the animation is not yet finished.
     * 当你想知道滑动的最新位置,就调用此方法,如果这个方法返回true,说明滑动还没完成
     */ 
public boolean computeScrollOffset() {}

/**
* Returns the current X offset in the scroll. 
* 
* @return The new X offset as an absolute distance from the origin.
* 返回当前相对于原始位置水平方向的绝对距离
*/
public final int getCurrX() {
   return mCurrX;
}

/**
* Returns the current Y offset in the scroll. 
* 
* @return The new Y offset as an absolute distance from the origin.
*/
public final int getCurrY() {
   return mCurrY;
}

/**
* Called by a parent to request that a child update its values for mScrollX
* 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重新绘制
* 如果子类使用Scroller来进行滑动,应该要实现该方法来更新mScrollX,mScrollY
*/
public void computeScroll() {
}
computeScroll()方法在View中

另外还有几个辅助方法
/**
 * 
 * Returns whether the scroller has finished scrolling.
 * 
 * @return True if the scroller has finished scrolling, false otherwise.
 * 获取滑动是否完成
 */
public final boolean isFinished() {
    return mFinished;
}

/**
  * Stops the animation. Contrary to {@link #forceFinished(boolean)},
  * aborting the animating cause the scroller to move to the final x and y
  * position
  *终止滑动的方法
  * @see #forceFinished(boolean)
  */
 public void abortAnimation() {
     mCurrX = mFinalX;
     mCurrY = mFinalY;
     mFinished = true;
 }

到此,使用Scroller的几个重要方法介绍完毕

2. Scroller使用

  • 第一步,初始化,直接new Scroller(Context)即可
  • 第二步,调用scroller的startScroll(int startX, int startY, int dx, int dy)方法,传入相应的参数
  • 第三步,重新控件的computeScroll()方法,在此方法中获取最新滑动的位置,先调用computeScrollOffset()请求新位置,并判断是否滑动完毕,然后调用getCurrX()和getCurrY()获取最新位置,注意,这个位置是相对于控件原始位置的绝对位置,所以我们调用scrollTo方法,让控件滑动到最新位置,然后invalidate()一下,请求重新位置最新位置。

使用优化,比如,在keyDown中,我们可以先判断下,动画是否执行完毕,没有的话,我们可以终止掉

if(!mScroller.isFinished()){
    mScroller.abortAnimation();
}