今天又看了一遍Android开发艺术探索的View事件体系,灵感突现,突然理解了滑动是怎么一回事,文章主要针对内容滑动,比如ScrollView的滑动。
小技巧:以ScrollView为例,往上滑的话,scrollY越大,往下滑的话,scrollY越小.
本文代码中的onTouchEvent里的获取新旧x,y值可以作为一种通用的写法
首先写一个类继承LinearLayout,然后初始化Scroller
private void init(Context context) {
scroller = new Scroller(context);
}
主要代码在onTouchEvent里面:
private int lastX;
//滑动时的上一个Y值,当在action_move里面时,gety值是新的,这时lastY还是旧的,所以可以相减
private int lastY;
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
// Log.d("alan","yStart--->"+y);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//这样写也可以
// lastX= (int) event.getRawX();
// lastY= (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
// Log.d("alan","y---->"+y+"***********"+"lastY---->"+lastY);
if (Math.abs(y) <= Math.abs(lastY)) {//上滑(新位置比老位置绝对值小)
int dyAbs = Math.abs(y - lastY);
scrollBy(0, dyAbs);
} else {//下滑
//lastY-y为负值
scrollBy(0, lastY - y);
}
// Log.d("alan","ACTION_MOVE y----->"+y);
break;
case MotionEvent.ACTION_UP:
break;
}
lastX = x;
lastY = y;
return true;
}
代码中获取新旧的x,y值可以作为一种通用的写法,以后直接使用,由于是竖直滑动,所以没有处理X值,在action_move里面判断是上滑还是下滑,然后用scrollBy,这个方法要传偏移值,而不是终点值(scrollTo是传终点值),由于滑动的是内容,所以要充分理解ScrollY这个值的意思(android 开发艺术探索中有讲),这里不能用scroller.startScroll()这个方法,是因为手指要实时滑动,而不是短时间内平滑滑动。
这样就完成了滑动的处理。
Scroller还可以用来做平滑的滑动,可以用下面这段代码:
public void smoothScollTo(int endX, int endY) {
// Log.d("alan","smoothScollTo");
int scrollY = getScrollY();
// Log.d("alan","scrollY---->"+scrollY);
int dy = endY - scrollY;
Log.d("alan", "scrollY--->" + scrollY + "**********" + "endY--->" + endY);
scroller.startScroll(0, scrollY, 0, dy, 20);
invalidate();
}
@Override
public void computeScroll() {
// Log.d("alan","computeScroll");
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
// Log.d("alan","scroller.getCurrY()---->"+scroller.getCurrY());
postInvalidate();
} else {
// Log.d("alan","getscrollY end---->"+getScrollY());
}
}
上面代码是在20ms内,将内容移到指定位置,当重绘时,会调用computeScroll,会如此反复下去,直到滑动结束。
代码和效果图已传到GitHub,
源码