android onTouch和手势基础详解

来源:互联网 发布:手机照片搞怪软件 编辑:程序博客网 时间:2024/05/22 15:16

onTouch事件
做什么都好先了解原理以后的工作就会更简单,关于手势以及我们熟悉的onclick,
onLongClick事件都是基于对onTouch事件的捕捉和处理。那么在使用手势工具类的前提下我们应该去学习了解基本的onTouch事件。

onTouch常用的以下4个事件:

1、ACTION_DOWN:
表示按下了屏幕,第一个执行也是必然执行的方法。

2、ACTION_MOVE:
表示为移动手势,会不断的执行直到触摸停止。

3、ACTION_UP :
表示为离开屏幕,触摸停止的时候执行。

4、ACTION_CANCEL:
表示取消手势,不会由用户产生,而是由程序产生的。
一个Action_DOWN, 多个ACTION_MOVE, 1个ACTION_UP,就构成了Android中众多的事件。

onTouch的参数
View
受到Touch事件的view对象

MotionEvent
包含的事件的详细信息,例如触摸点的信息,触摸事件类型的信息等
MotionEvent的方法例如getRowX所描述的都是触摸点的信息。

几个重要方法的说明:

getRowX:触摸点相对于屏幕的X坐标
getRowY:触摸点相对于屏幕的Y坐标
getX: 触摸点相对于view的X坐标 :即对其进行touch监听的那个view
getY: 触摸点相对于view的X坐标
getTop: 按钮左上角相对于父view(LinerLayout)的y坐标
getLeft: 按钮左上角相对于父view(LinerLayout)的x坐标

onTouch的返回值
作用:
这里的返回值代表的是,对于这个触摸事件touch是否已经处理完成。
如果我们设置返回值为true代表的是处理完成,这样就不会再传递给下一个对象。也就是说后面的控件或者对象就不会接收到触摸事件了。
反之,后面的对象或控件会在此接收到这个触摸事件并被调用。
详细的可以看我的这篇文章:最容易理解的触摸事件传递机制

实践
在学习基础知识之后,我们来看看如何使用这些来实现一个可以拖动的view吧。

public class MoveTouch implements View.OnTouchListener {    private int[] temp = new int[2];    private int dx, dy;    private boolean isMove = false;    private Context context;    public MoveTouch(Context context) {        this.context = context;    }    @Override    public boolean onTouch(View v, MotionEvent event) {        int x = (int) event.getRawX();        int y = (int) event.getRawY();        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                dx = (int) event.getRawX();                dy = (int) event.getRawY();                temp[0] = x - v.getLeft();                temp[1] = y - v.getTop();//              temp[0]=(int)event.getX();  //获取触摸点view 距离该view左边的距离 等同于 x-v.getLeft() 为了 保证坐标的正确性建议使用上面的方法//              temp[1]=(int)event.getY(); //按 y - temp[1] 这样得到的不是该view距离父view的距离,而是距离屏幕顶部的距离 包括状态栏等                isMove = false;                break;            case MotionEvent.ACTION_MOVE:                /**                 * 对view的按下的操作进行判断是否是移动操作                 */                if (Math.abs(dx - x) > 10 || Math.abs(dy - y) > 10) {                    isMove = true;                }                if (isMove) {                    v.layout(x - temp[0], y - temp[1], x + v.getWidth() - temp[0], y + v.getHeight() - temp[1]);                }                break;            case MotionEvent.ACTION_UP:                if (!isMove) {                    Toast.makeText(context, "被点击了", Toast.LENGTH_SHORT).show();                }                break;        }        return true;//表示我自己处理这个触摸事件,不往下传递    }}

接下来再看看触摸事件和手势
手势操作
关于手势操作,这里其实说的是Android提供的工具类,通过GestureDetector 类来识别和处理onTouch事件,简化使用。

一般用到下面的三个类。

android.view.GestureDetector
手势操作的识别类,通过他来使用下面的识别接口。

android.view.GestureDetector.SimpleOnGestureListener
手势识别的接口类,使用他可以按需重载自己想要的方法,方法多

android.view.GestureDetector.OnGestureListener;
手势识别的类,SimpleOnGestureListener接口的父类。使用他需要实现他所有的方法。

方法说明:
OnGestureListener有下面的几个方法:

按下(onDown):
在按下时调用。

抛掷(onFling):
手指在触摸屏上迅速移动,并松开的动作。

长按(onLongPress):
手指按在持续一段时间,并且没有松开。

滚动(onScroll):
手指在触摸屏上滑动。

按住(onShowPress):
手指按在触摸屏上,它的时间范围在按下起效,在长按之前。

抬起(onSingleTapUp):
手指离开触摸屏的那一刹那。

SimpleOnGestureListener比OnGestureListener多出来的方法:

双击(onDoubleTap)
双击的第二下Touch down时触发

双击事件(onDoubleTapEvent)
双击的第二下Touch down和up都会触发一次,可用e.getAction()区分。

实践
其实看到上面的介绍应该可以看出来,其实手势就是对我们的触摸事件的一些操作进行了封装,变得更简单,简洁,方便我们的使用

public class MyGesture implements View.OnTouchListener, GestureDetector.OnGestureListener {    private Context context;    private GestureDetector gestureDetector;    private int[] temp = new int[2];    private View v;    public MyGesture(Context context) {        this.context = context;        gestureDetector = new GestureDetector(context, this);    }    @Override    public boolean onDown(MotionEvent e) {        temp[0]=(int)e.getRawX()-v.getLeft();        temp[1]=(int)e.getRawY()-v.getTop();        return false;    }    /**     *  用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发     // 注意和onDown()的区别,强调的是没有松开或者拖动的状态     * @param e     */    @Override    public void onShowPress(MotionEvent e) {    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        Toast.makeText(context, "被点击了", Toast.LENGTH_SHORT).show();        return false;    }    /**     * 按住然后滑动  e1 手开始触碰屏幕的位置的MotionEvent对象     * @param e1     * @param e2  手结束触碰屏幕的位置的MotionEvent对象     * @param distanceX     * @param distanceY     * @return     */    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        int x=(int)e2.getRawX();        int y=(int)e2.getRawY();        v.layout(x-temp[0],y-temp[1],x+v.getWidth()-temp[0],y-temp[1]+v.getHeight());        return false;    }    @Override    public void onLongPress(MotionEvent e) {    }    /**     * 快速滑动并且移开     * @param e1     * @param e2     * @param velocityX     * @param velocityY     * @return     */    @Override    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {        return false;    }    @Override    public boolean onTouch(View v, MotionEvent event) {        this.v=v;        gestureDetector.onTouchEvent(event);        return true;    }}

如果使用GestureDetector.SimpleOnGestureListener代码更简洁这里我们就不是实现了,而是继承GestureDetector.SimpleOnGestureListener这个类

public class MySimpleGesture extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener{    @Override    public boolean onTouch(View v, MotionEvent event) {        return false;    }    @Override    public boolean onDown(MotionEvent e) {        return super.onDown(e);    }    @Override    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {        return super.onScroll(e1, e2, distanceX, distanceY);    }    @Override    public boolean onSingleTapUp(MotionEvent e) {        return super.onSingleTapUp(e);    }}

实现我就不写了,有兴趣的童鞋可以做一下,练练手。~

0 0
原创粉丝点击