1 序言
在安卓中,一些应用总是会使用滑动来让自己得到改善,例如植物大战僵尸2中选择植物,就有用到滑动.这些效果本质上来说就是移动一个View,改变其当前所在的位置.所以,如果要实现View的滑动,就必须监听用户的触摸事件,并监听传入的坐标,来实现滑动.
2 安卓坐标系
在安卓中,屏幕左上角为Android坐标系的原点,这个点以右边边和下边为正方向,在触碰事件中,getRawX和getRawY是获得Android坐标系的坐标.
3 视图坐标系
视图坐标系描述了子视图在父视图中的位置,和安卓坐标系相同,他也是以右边和下边为正方向,在触碰事件中,getX和getY获得的是视图坐标系的XY坐标.我们也可以调用View的方法,来获取坐标.
视图左侧位置 view.getLeft()
视图右侧位置 view.getRight()
视图顶部位置 view.getTop();
视图底部位置 view.getBottom();
视图宽度 view.getWidth();
视图高度 view.getHeight()
4 触碰事件---MotionEvent
public static final int ACTION_DOWN = 0;单点触摸动作
public static final int ACTION_UP = 1;单点触摸离开动作
public static final int ACTION_MOVE = 2;触摸点移动动作
public static final int ACTION_CANCEL = 3;触摸动作取消
public static final int ACTION_OUTSIDE = 4;触摸动作超出边界
public static final int ACTION_POINTER_DOWN = 5;多点触摸动作
public static final int ACTION_POINTER_UP = 6;多点离开动作
MotionEvent封装了用户的触碰操作,以上是一些常用的常量.
5 获取MotionEvent
一般情况下,我们是通过重写TouchEvent(MotionEvent event)方法来获得MotionEvent类.在方法中,我们只需要调用event.getAction就可以获得触碰事件的类型,如下面的例子所示.
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i("test",event.getAction()+"");
}
6 实现滑动
前面说了,本质上,滑动就是改变View的坐标,我们了解了坐标系和触碰事件之后,我们就可以调用API来实现滑动了,在一个View中,我们可以通过scrollTo和scrollBy来实现改变View位置,scrollTo的作用是移动到一个具体的位置,而scrollBy表示移动的增量(在原有的基础上移动的距离).但是需要注意,如果我们想让View本身移动而不是他的content的话,我们需要在利用父类(getParent())来调用这两个方法.我们先做个试验,看一下,
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
((View)getParent()).scrollTo(10, 10);
break;
default:
break;
}
return super.onTouchEvent(event);
}
我们调用ScrollTo方法,让他往X坐标正方向移动10个单位,但是发现是往反边移动的,所以我们认为当我们设置scrollTo的参数为正数时,他是往反方向移动的,而负数是往正方向移动的,现在我们看看Scroller类,没错,也就是我们的这次的猪脚登场了,他和前面的两个方法有着很大的联系,但是前面两个方法的移动都是瞬间完成的,移动过程非常不平滑.而Scroller类可以帮我们实现平滑移动.一般情况下,使用Scroller,需要三个步骤.
- 初始化Scroller,通过构造函数来创建一个Scroller对象
- 重写computeScroll()方法,实现平滑移动
- startScroll开启模拟移动
我们先来重写computeScroll()方法,他是Scroll类的核心,如下所示:
@Override
public void computeScroll() {
if(mScroller.computeScrollOffset()){
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
首先我们分析一下这个方法,这个方法没办法主动调用 ,它是通过ondraw方法来调用的.所以我们想使用它,就要调用ondraw()方法,我们调用刷新invalidate()函数,间接完成了调用,,Scroll对象的computeScrolloffset方法,它代表着一个bool变量,当我们滑动操作完成时,他就是false的,这样我们就理清思路了下面我们调用startScroll方法来开启滑动
.
private void smooth(int dx,int dy){
mScroller.startScroll(getScrollX(), 0, dx-getScrollX(), dy,5000);
invalidate();
}
在这个startScroll方法中的五个参数依次代表:
- 开始滑动的X坐标
- 开始滑动的Y坐标
- 目标的X坐标
- 目标的Y坐标
- 全部移动完成所需要的时间
至此,我们算是非常熟悉和了解Scroller了