Android View的触摸事件机制

1. 触摸事件的基本类型
     1). down: 按下
     2). move: 移动
     3). up: 离开

2. 事件对象产生的顺序
     1). down-->move-->move-->....-->up
     2). 每个事件对象产生后, 都会找到一个消费者来消费处理此事件

3. 事件相关API
     1). MotionEvent: 代表对UI的操作单元的类, 它的对象在用户触摸UI时系统自动创建基对象, 并将相关的数据保存在此对象中
ACTION_DOWN=0 : down类型值
ACTION_UP=1 : up类型值 
ACTION_MOVE=2 : move类型值 
int getAction() : 得到事件类型值

float getX() : 得到事件的X轴坐标(相对于当前View的左顶点)
float getRawX() : 得到事件的X轴坐标(相对于屏幕的左顶点)
float getY() : 得到事件的Y轴坐标(相对于当前View的左顶点)
float getRawY() : 得到事件的Y轴坐标(相对于屏幕的左顶点)
     2). Activity
               boolean dispatchTouchEvent(MotionEvent event) : 分发事件  
               boolean onTouchEvent(MotionEvent event) : 处理事件的回调
     3). View
               boolean dispatchTouchEvent(MotionEvent event): 分发事件
            
               setOnClickListener(OnClickListener l) : 设置触摸事件监听器对象
               private OnTouchListener mOnTouchListener; //触摸事件监听器对象变量
               public interface OnTouchListener {  //事件监听器接口
                  boolean onTouch(View v, MotionEvent event);  // 监听器对象的回调方法
               }

               boolean onTouchEvent(MotionEvent event)  : 事件监听回调方法

               setOnclickListener(OnclickListener listener) : 设置点击监听器
               setOnLongClickListener(OnLongClickListener listener) : 设置长按事件监听器
     4). ViewGroup
               boolean dispatchTouchEvent(MotionEvent ev) : 重写View的此方法, 如果当前ViewGroup不拦截, 会分发给对应的子View处理事件
               boolean onInterceptTouchEvent(MotionEvent ev) : 拦截触摸事件, 返回值如果为true表示拦截,后面的事件就会交给当前View来处理, 默认为false
               requestDisallowInterceptTouchEvent(boolean disallowIntercept) : 如果参数为true, 使当前View及其外层的所有父View不能拦截后面的事件

4. View的事件处理
     1). Touch事件的方法执行顺序: 
          ①. dispatchTouchEvent()
          ②. setOnTouchListener的onTouch()
          ③. onTouchEvent()
     2). 执行的详细过程
          ①. 在dispatchTouchEvent()会判断是否设置了Touch监听器?
               如果没有直接进入②
               如果有, 调用监听器的onTouch()方法, 如果onTouch方法返回true到此结束, 如果返回false进入②
          ②. 调用onTouchEvent()
               在down时, send一个延时500ms的消息准备触发长按事件监听回调)
               如果0.5s内在产生了up事件, 此时就会移除长按的延时消息, 就会去执行点击事件监听回调
               如果0.5内没有产生up事件, 也没有离开, 就会调用长按事件监听回调方法, 如果返回的值是true就不可能再触发点击监听回调了, 否则还会触发.
     3). 说明:
          ①. 如果view的onTouch()(监听器回调)或onTouchEvent(监听回调)在down时返回true, 那第一个move事件就会交给当前View处理, 否则后面的所有事件都不会到达此View了
          ②. 如是move事件处理返回true, 下一个move/up事件就会交给当前View处理,否则就会找父View或Activity处理
          ③. 整体原则: 每个Event对象创建后, 最终肯定会有一个消费者: 可能是View, 也可能是ViewGroup, 实在不行就交给Activty消费处理

5. ViewGroup的事件处理
     1). 相关方法执行顺序:
          ①. dispatchTouchEvent()
          ②.onInterceptTouchEvent()
          ③. 对应子View的dispatchTouchEvent()
     2). 执行的详细过程:
          ①. 在dispatchTouchEvent()中, ACTION_DOWN时, 判断是否拦截,如果没有拦截,则找到包含当前x,y坐标的子View,赋值给mMotionTarget,
               然后调用mMotionTarget.dispatchTouchEvent()处理down事件
          ②. 在dispatchTouchEvent()中, ACTION_MOVE时, 判断是否拦截,如果没有拦截,则直接调用mMotionTarget.dispatchTouchEvent(ev)
          ③. 在dispatchTouchEvent()中, ACTION_UP时, 判断是否拦截,如果没有拦截,则直接调用mMotionTarget.dispatchTouchEvent(ev)
          ④. 如果没有找到合适的子View来消费当前event, 则将自己当成View来处理event
     3). 关于拦截:
          ①. 如何拦截?: ViewGroup中onInterceptTouchEvent()默认返回false, 也就是不拦截, 如果想拦截就重写此方法, 并返回true, 这样事件就不会分发给子View处理
          ②. 如何不被拦截?: 如果子View不希望父View(也就是当前ViewGroup)拦截event, 子View可以执行: getParent().requestDisallowInterceptTouchEvent(true)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值