触摸事件 Touch MotionEvent ACTION

MotionEvent简介



当用户触摸屏幕时,将创建一个MontionEvent对象,MotionEvent包含了关于发生触摸的位置、时间信息,以及触摸事件的其他细节。

获取MontionEvent对象的方法有:
  • 在View或Activity的onTouchEvent方法中: public boolean onTouchEvent(MotionEvent event) {}
  • 实现OnTouchListener接口后在onTouch方法中: public boolean onTouch(View v, MotionEvent event) {}
我们可以从一个MotionEvent对象中获得哪些信息呢? 1、事件的类型       可以通过getAction()获得事件的类型,在android2.2之后加入了对多点触控的支持,多点触控时需使用getActionMasked()方法       注意:event.getActionMasked() 和 event.getAction() & MotionEvent.ACTION_MASK 是等价的       getActionMasked的低8位是动作类型信息(和getAction的值是一样的),8-15位是触控点的索引信息(即表示是哪一个触控点的事件)       具体看这里:http://my.oschina.net/banxi/blog/56421 
  • ACTION_DOWN: 表示用户开始触摸(在第一个点被按下时触发)
  • ACTION_MOVE: 当有点在屏幕上移动时触发,注意的是,由于灵敏度很高,所以基本上只要有点在屏幕上,此事件就会不停地被触发
  • ACTION_UP:表示用户抬起了手指(当屏幕上唯一的点被放开时触发)
  • ACTION_CANCEL:表示手势被取消了
  • ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界
  • ACTION_POINTER_DOWN:当屏幕上已经有一个点被按住,此时再按下其他点时触发
  • ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(非最后一个点)
2、事件发生的位置
  • getX() 获得事件发生时,触摸的中间区域相对view的触摸位置坐标(不会超过view的长度和宽度)
  • getRawX() 和上面getX()不同的是,此方法获得的是相对屏幕的位置坐标
  • getX(int pointerIndex)  在多点触控中,用来获取第pointerIndex个触控点的x位置坐标
3、其他信息
  • getPointerCount(); //获取触控点的数量,比如2则可能是两个手指同时按压屏幕
  • getPointerId(nID); //对于每个触控的点的细节,我们可以通过一个循环执行getPointerId方法获取索引
  • getPressure(nID); //LCD可以感应出用户的手指压力,当然具体的级别由驱动和物理硬件决定的
  • getDownTime() //按下开始时间
  • getEventTime() // 事件结束时间
  • getEventTime()-event.getDownTime()); //总共按下时花费时间
  • getEdgeFlags():当事件类型是ActionDown时可以通过此方法获得手指触控开始的边界,如果是的话,有如下几种值:EDGE_LEFT、EDGE_TOP、EDGE_RIGHT、EDGE_BOTTOM

定义的常量



MotionEvent中定义的常量有以下几个

touch事件:
  • ACTION_DOWN = 0;单点触摸动作
  • ACTION_UP = 1;单点触摸离开动作
  • ACTION_MOVE = 2;触摸点移动动作
  • ACTION_CANCEL = 3;触摸动作取消
  • ACTION_OUTSIDE = 4;触摸动作超出边界
  • ACTION_POINTER_DOWN = 5;多点触摸动作
  • ACTION_POINTER_UP = 6;多点离开动作
其他:
  • ACTION_HOVER_MOVE = 7;
  • ACTION_SCROLL = 8;
  • ACTION_HOVER_ENTER = 9;
  • ACTION_HOVER_EXIT = 10;
  • ACTION_MASK = 0X000000ff 掩码常量
  • ACTION_POINTER_INDEX_MASK = 0X0000ff00 动作掩码
  • ACTION_POINTER_INDEX_SHIFT = 8 触摸点索引掩码,获取触摸点索引需要移动的位数

双指缩放图片



public class MainActivity extends Activity implements OnTouchListener {
    private ImageView myImageView;

    private int mode = 0; //触摸点数

    private float oldDist;

    private float scale = 1;

    private float lastScale = 1;//记录手指全部离开时的缩放比例,下次缩放时是在次基础上进行的

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        myImageView = new ImageView(this);

        myImageView.setImageResource(R.drawable.ic_launcher);

        myImageView.setBackgroundColor(0x8822ffff);//从背景可以看出,此ImageView 是占用整个屏幕大小的

        myImageView.setScaleType(ScaleType.MATRIX);

        myImageView.setOnTouchListener(this);

        setContentView(myImageView);

    }

    @Override

    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getAction() & MotionEvent.ACTION_MASK) {

        case MotionEvent.ACTION_DOWN:

            mode = 1;

            Log.e("View", "ACTION_DOWN,触摸点数为1");

            break;

        case MotionEvent.ACTION_UP://当屏幕上唯一的点被放开时触发

            lastScale = scale;

            mode = 0;

            Log.e("View", "ACTION_UP,触摸点数为0");

            break;

        case MotionEvent.ACTION_POINTER_UP://当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)

            mode -= 1;

            Log.e("View", "ACTION_POINTER_UP,触摸点数-1");

            break;

        case MotionEvent.ACTION_POINTER_DOWN://当屏幕上已经有一个点被按住,此时再按下其他点时触发

            oldDist = spacing(event);//第二个点按下时的和第一个点的距离 

            mode += 1;

            Log.e("View", "ACTION_POINTER_DOWN,触摸点数+1," + oldDist);

            break;

        case MotionEvent.ACTION_MOVE://当有点在屏幕上移动时触发

            if (mode >= 2) {

                float newDist = spacing(event);//移动过程中,第二个点和第一个点的距离 

                if (Math.abs(newDist - oldDist) > 10) {//减小灵敏度

                    scale = lastScale * newDist / oldDist;

                    Log.e("View", "ACTION_MOVE,缩放比例为" + scale);

                    Matrix mMatrix = new Matrix();

                    mMatrix.setScale(scale, scale);

                    myImageView.setImageMatrix(mMatrix);

                }

                break;

            }

        }

        return true;//若view的onTouch返回true(只有这样才能接收事件),那么onTouchEvent就收不到事件了(包括down事件)

    }

    /**

     * 返回两个点之间的距离,注意,如果只有一个触摸点的话调用getX(1)就挂掉了,为减少冗余的判断,我们可以放在try中

     */

    private float spacing(MotionEvent event) {

        float x = event.getX(0) - event.getX(1);

        float y = event.getY(0) - event.getY(1);

        return FloatMath.sqrt(x * x + y * y);

    }

}

缩放、移动图片



public class MainActivity extends Activity {

    private ImageView imageView;

    @Override

    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);

        imageView = (ImageView) this.findViewById(R.id.imageView);

        imageView.setOnTouchListener(new TouchListener());

    }

    private final class TouchListener implements OnTouchListener {

        /** 记录是拖拉照片模式还是放大缩小照片模式 */

        private int mode = 0;// 初始状态  

        /** 拖拉照片模式 */

        private static final int MODE_DRAG = 1;

        /** 放大缩小照片模式 */

        private static final int MODE_ZOOM = 2;

        /** 用于记录开始时候的坐标位置 */

        private PointF startPoint = new PointF();

        /** 用于记录拖拉图片移动的坐标位置 */

        private Matrix matrix = new Matrix();

        /** 用于记录图片要进行拖拉时候的坐标位置 */

        private Matrix currentMatrix = new Matrix();

        /** 两个手指的开始距离 */

        private float startDis;

        /** 两个手指的中间点 */

        private PointF midPoint;

        @Override

        public boolean onTouch(View v, MotionEvent event) {

            /** 通过与运算保留最后八位 MotionEvent.ACTION_MASK = 255 */

            switch (event.getAction() & MotionEvent.ACTION_MASK) {

            // 手指压下屏幕

            case MotionEvent.ACTION_DOWN:

                mode = MODE_DRAG;

                // 记录ImageView当前的移动位置

                currentMatrix.set(imageView.getImageMatrix());

                startPoint.set(event.getX(), event.getY());

                break;

            // 手指在屏幕上移动,该事件会被不断触发

            case MotionEvent.ACTION_MOVE:

                // 拖拉图片

                if (mode == MODE_DRAG) {

                    float dx = event.getX() - startPoint.x; // 得到x轴的移动距离

                    float dy = event.getY() - startPoint.y; // 得到x轴的移动距离

                    // 在没有移动之前的位置上进行移动

                    matrix.set(currentMatrix);

                    matrix.postTranslate(dx, dy);

                }

                // 放大缩小图片

                else if (mode == MODE_ZOOM) {

                    float endDis = distance(event);// 结束距离

                    if (endDis > 10f) { // 两个手指并拢在一起的时候像素大于10

                        float scale = endDis / startDis;// 得到缩放倍数

                        matrix.set(currentMatrix);

                        matrix.postScale(scale, scale, midPoint.x, midPoint.y);

                    }

                }

                break;

            // 手指离开屏幕

            case MotionEvent.ACTION_UP:

                // 当触点离开屏幕,但是屏幕上还有触点(手指)

            case MotionEvent.ACTION_POINTER_UP:

                mode = 0;

                break;

            // 当屏幕上已经有触点(手指),再有一个触点压下屏幕

            case MotionEvent.ACTION_POINTER_DOWN:

                mode = MODE_ZOOM;

                /** 计算两个手指间的距离 */

                startDis = distance(event);

                /** 计算两个手指间的中间点 */

                if (startDis > 10f) { // 两个手指并拢在一起的时候像素大于10

                    midPoint = mid(event);

                    //记录当前ImageView的缩放倍数

                    currentMatrix.set(imageView.getImageMatrix());

                }

                break;

            }

            imageView.setImageMatrix(matrix);

            return true;

        }

        /** 计算两个手指间的距离 */

        private float distance(MotionEvent event) {

            float dx = event.getX(1) - event.getX(0);

            float dy = event.getY(1) - event.getY(0);

            /** 使用勾股定理返回两点之间的距离 */

            return FloatMath.sqrt(dx * dx + dy * dy);

        }

        /** 计算两个手指间的中间点 */

        private PointF mid(MotionEvent event) {

            float midX = (event.getX(1) + event.getX(0)) / 2;

            float midY = (event.getY(1) + event.getY(0)) / 2;

            return new PointF(midX, midY);

        }

    }

}

来自为知笔记(Wiz)

时间: 2024-10-06 16:25:50

触摸事件 Touch MotionEvent ACTION的相关文章

JS事件监听手机屏幕触摸事件 Touch

JS移动客户端--触屏滑动事件 移动端触屏滑动的效果其实就是图片轮播,在PC的页面上很好实现,绑定click和mouseover等事件来完成.但是在移动设备上,要实现这种轮播的效果,就需要用到核心的touch事件.处理touch事件能跟踪到屏幕滑动的每根手指. 以下是四种touch事件 touchstart:     //手指放到屏幕上时触发 touchmove:      //手指在屏幕上滑动式触发 touchend:    //手指离开屏幕时触发 touchcancel:     //系统取

js 触摸事件 touch

先上实例代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0"> <title>touch</title> <style t

[转]starling教程-触摸事件(Touch Events)(四)

在前面提到过,Starling是Sparrow的姊妹篇,正因为这样,Starling里的touch事件的机制其实是为移动设备的触摸交互设计的,所以当你使用它进行使用鼠标交互的桌面应用开发时,第一眼会感觉有些困惑. 首先,如果你看一下starling的类结构图的话,你会发现starling和本地显示列表结构不同的地方在于它没有InteractiveObject类(InteractiveObject 类是用户可以使用鼠标和键盘与之交互的所有显示对象的抽象基类),所有的显示对象使用默认的交互,换句话说

Android触摸事件机制

前言 随着科学技术的发展,智能手机早已成为我们当代人身边必不可少的"伙伴"之一,堪比对象女友.每天我们对着手机重复的做着点击.滑动操作,而手机则随着我们的操作给我们展示她的精彩. - 废话到此结束. 看到这里,即使不是作为移动端码农的你也应该知道触摸事件对手机(经典键盘机除外)的重要性了. 什么是触摸事件 顾名思义,就是触摸手机屏幕后产生的事件.这时候请你拿出手机,点击屏幕中的某个按钮(不要松手),移动一段距离,松手. 这个过程一般会产生如下几个事件: 点击(Down)事件 移动(Mo

Android中TouchEvent触摸事件机制

当我们的手指在Android屏幕上点击或滑动时,就会触发触摸事件TouchEvent.在App中ViewGroup和View存在多级嵌套,在最外层的是Activity,最内层的View,介于Activity与View之间的是一些ViewGroup.本文为了简化讨论,我们假设一个Activity中只有一个ViewGroup,这个ViewGroup中只有一个View.当我们用手指触摸到View的UI时,就会产生触摸事件TouchEvent,总的过程如下图所示: 首先是最外层的Activity接收到该

IOS 触摸事件分发机制详解

欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案: 某个点击消息由父视图来处理,子视图怎么把消息传递给父视图 这个按钮不灵敏,怎么扩大点击响应区域 怎么在一个页面处理手绘.表情拖动放缩.文本编辑三种消息 阅读本文,你会明白两个问题:IOS如何找到响应者.响应者是如何做出响应,明白这两个问题你就能解决类似上述的疑难杂症.通过控制Hit-test v

Android触摸事件

简介: 做了一个语音发送UI的小demo. 按下显示语音窗口,根据音量调节UI音量显示,上划至窗口显示取消发送. 原理: 1:获取什么事件来执行操作: 给Button添加setOnTouchListener事件,获得触摸事件,在滑动事件中得到当前显示控件的坐标,然后根据当前触摸位置与坐标进行判断来确定是否取消.在触摸离开的事件中来确定是否处理发送的请求. 2:更新音量值: 在线程中得到录音的音量大小,然后用handler发送到activity中进行UI更新. 详解事件: 通过public boo

HTML5触摸事件(touchstart、touchmove和touchend) (转)

HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应用实战性不是太强,所以在这里基本省略,咱们只分享应用广泛兼容不错的事件,日后随着兼容情况提升以后再陆续添加分享.今天为大家介绍的事件主要是触摸事件:touchstart.touchmove和touchend. 一开始触摸事件touchstart.touchmove和touchend是iOS版Safari浏览器为了向开发人员传达一些信息新添加的事件.因为iOs设备既没有鼠标也没有键盘,所以在为移动Safari浏览器开发交互性网页的时

Android触摸事件(一)-TouchEventHelper

文件夹 文件夹 概述 关于更新 2016-08-31 2016-06-20 关于单点触摸事件singleTouch 单击的两种方式 关于双击事件 双击事件的检測逻辑 双击事件触发的时机 关于多点触摸事件multiTouch 两点触摸中的移动事件 两点触摸事件的触发过程 两点触摸的事件 实现 变量定义 触摸事件流程 自己定义事件计时方案 自己定义事件触发区域 触摸事件处理规则 关于回调的方法 触摸事件处理源代码 双击事件的优化处理 怎样检測当次触摸事件的单击事件 怎样检測触发双击事件 辅助补充逻辑