上一篇博客提到了使用scrollTo,scrollBy来实现滑动。那既然提到scrollBy,scrollTo,那就简单来说下Scroller类。
两者十分相似,有着千丝万缕的联系。那他们又有什么区别?分别的使用场景是什么呢?
Scroller可以现实带动画的平滑效果,而scrollTo,scrollBy则是瞬间完成的。控件随着手指的移动而移动,放手回到初始位置,这个简单的效果,可以用scrollby和Scroller类一起完成,第一阶段控件随着手移动用scrollby实现,因为他需要即时反馈的效果,而放手后回到原始位置可以用Scroller比较恰当,不会太突兀。代码如下:
public class ScrollWithScrollerView extends View{
private int mLastX;
private int mLastY;
private Scroller mScroller;
public ScrollWithScrollerView(Context context) {
this(context, null);
}
public ScrollWithScrollerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public ScrollWithScrollerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mScroller = new Scroller(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
break;
case MotionEvent.ACTION_MOVE:
int dx = x - mLastX;
int dy = y - mLastY;
((View)getParent()).scrollBy(-dx, -dy);
break;
case MotionEvent.ACTION_UP:
View parent = (ViewGroup)getParent();
mScroller.startScroll(parent.getScrollX(),parent.getScrollY(),-parent.getScrollX(),-parent.getScrollY(),1500);
invalidate();
break;
}
return true;
}
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
invalidate();
}
}
}
在使用Scroller类的时候核心是要重写computeScroll()。因为系统在绘制View的时候会在ondraw方法中调用该方法。这个方法实际上就是使用scrollTo方法,再结合scroller对象,帮助获取当前的移动的滚动值,通过不断的瞬间移动一段微小的距离来现实整体上一点平滑的移动效果,一般情况下,重写computeScroll()可以使用一下模板
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()){
((View)getParent()).scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
invalidate();
}
}
computeScrollOffset方法是来判断是否完成整个滑动,返回false表示完成整个滑动过程。
上面唯一要注意的是,不要忘了invalidate(),因为computeScroll方法不会自动调用,要通过invalidate()-draw()-computeScroll()来间接调用computeScroll方法。
开始滑动的两个方法
startScroll(int startX, int startY, int dx, int dy, int duration)
startScroll(int startX, int startY, int dx, int dy)
这两个方法的本质是一样的。也非常好理解参数的含义,需要注意的是调用完此方法,不要忘了invalidate(),因为需要间接调用computeScroll方法开始模拟滑动。
Scroller类非常强大,Android中许多厉害的空间内部用的都是Scroller,如ListView等,这篇文章只是简单的介绍了一下它的用法。下一篇博客简单介绍下ViewDragHelper