集册 Android&Java 技术笔记 安卓系统点击事件处理框架

安卓系统点击事件处理框架

—— 安卓系统点击事件处理

欢马劈雪     最近更新时间:2020-08-04 05:37:59

105

参考PPT

安卓系统点击事件处理框架

  • 用户的点击事件均被包装为MotionEvent
  • MotionEvent描述了用户的行为
    • ACTION_DOWN
    • ACTION_UP
    • ACTION_MOVE
    • ACTION_POINTER_DOWN
    • ACTION_POINTER_UP
    • ACTION_CANCEL
    • 使用MotionEventCompat.getActionMasked(ev)获取MotionEvent对应的action
  • MotionEvent还包括以下信息
    • 点击的位置(x, y坐标)
    • 触点的数量(手指)
    • 事件发生的时间戳
  • 任何一个手势,都是以ACTION_DOWN起始,ACTION_UP结束
  • 事件从Activity的dispatchTouchEvent()函数开始,沿着View层次树依次向下传递
    • 父元素把事件dispatch到子元素
    • 事件能在任意阶段被intercept
  • 事件会沿着View层次树依次向下传递,然后又反向向上传递,直到被“消费”
    • View如果对手势感兴趣,就必须消费掉ACTION_DOWN的事件
    • 出于性能的考虑,同一手势的后续事件将不会按照完整路径进行传递,而是直接传递到消费了ACTION_DOWN事件的View
    • 如果所有的View(ViewGroup)都没有消费掉事件,那它将传递到Activity的onTouchEvent()函数中,并结束传递过程,即如果没有被消费,也不会再继续传递了
  • 可选的OnTouchListener能在任一View(ViewGroup)上intercept事件,事件被intercept之后,后面的调用将被传入ACTION_CANCEL?啥意思??
  • Activity.dispatchTouchEvent()
    • 总是首先被调用
    • Sends event to root view attached to Window
    • 如果所有的View(ViewGroup)都没有消费该事件,那么Activity.onTouchEvent()将被调用,而且这个函数是最后一个被调用的函数
  • ViewGroup.dispatchTouchEvent()
    • 首先调用onInterceptTouchEvent()函数,判断是否需要拦截
      • 检查是否应该替代子view的处理
      • Passes ACTION_CANCEL to active child
      • 如果要消费掉同一手势的所有后续事件,需要返回true
    • 对所有的孩子,以添加顺序的逆序进行遍历
      • 如果点击在孩子的边界内,则调用child.dispatchTouchEvent()
      • 如果没有被当前的孩子消费,则传递到下一个孩子
    • 如果所有的孩子都未消费该事件,则传递给listener,OnTouchListener.onTouch()
    • 如果没有listener,或者listener也未消费,则自己处理,调用ViewGroup.onTouchEvent()
    • Intercepted events jump over child step
  • View.dispatchTouchEvent()
    • 如果被设置了OnTouchListener,那么将先把事件发送到listener,调用View.OnTouchListener.onTouch()
    • 如果listener没有消费事件,将调用View.onTouchEvent(),即自己处理点击事件
  • 例子
    • View对事件不感兴趣
    • View对事件感兴趣
    • 事件被ViewGroup intercept
  • 小结
    • 手势以ACTION_DOWN起始,以ACTION_UP结束
    • ACTION_DOWN,在每一层View上都会调用dispatchTouchEvent(),该View会判断是否对接下来的手势感兴趣,后续的点击事件将直接传递到感兴趣的View
    • ViewGroup可以intercept一个手势,因为onInterceptTouchEvent()是在dispatchTouchEvent()函数中最先被调用的,如果onInterceptTouchEvent()返回true,它的孩子将不会收到该手势的后续事件

自定义点击事件处理

展开阅读全文