解码自定义View-触摸反馈

  触摸反馈应该是自定义view最简单的部分了,不过内部的原理是比较复杂的,去了解里面的核心机制,须要本身去阅读源码,才能更好理解整个触摸机制,固然,知其因此然也是远远不够的,下面我就带你们了解自定义view触摸机制的难点重点。面试

一. 概念

触摸反馈就是View对你的用户的触摸事件进行自定义,重写onTouchEvent方法算法

二.自定义单View的触摸反馈

  • 重写 onTouchEvent(),在方法内部定制触摸反馈算法ui

  • 是否消费事件取决于 ACTION_DOWN 事件 或 POINT_DOWN 事件是否返回 为truespa

  • MotionEventcode

    • getActionMasked() 和 getAction()递归

    • POINT_DOWN / POINT_UP 和 getActionIndex()事件

三.触摸反馈的流程

  • Activity.dispatchEvent()get

    • 递归: ViewGroup(View).dispatchTouchEvent()
    • ViewGroup.onInterceptTouchEvent()
    • child.dispatchTouchEvent()
    • super.dispatchTouchEvent()
    • View.onTouchEvent()
  • Activity.onTouchEvent()源码

四.View.dispatchTouchEvent()

  • 若是设置了 OnTouchListener ,调用 OnTouchListener.onTouch()it

    • 若是 OnTouchListener 消费了该事件,返回 true
    • 若是 OnTouchListener 没有消费该事件,继续调用本身的 onTouchEvent 并返回 和 onTouchEvent相同的结果
  • 若是没有设置OnTouchListener,同上

五.ViewGroup.dispatchTouchEvent()

  • 若是是用户初次按下 (ACTION_DOWN) ,清空TouchTargets 和 DISALLOW_INTERCEPT 标记

    • 拦截处理 getParent().requestDisallowInterceptTouchEvent()
    • 若是不拦截并非 CANCEL 事件,而且是down 或者 POINT_DOWN ,尝试把pointer (手指) 经过 touchTarget 分配给子View;而且 若是 分配给 新的子View ,调用 child.dispatchEvent 把 DOWN 事件传给子View
  • 看有没有 TouchTargets

    • 若是没有,调用super.dispatchEvent()
    • 若是有,调用child.dispatchEvent() 把事件传给对应的子View(若是有的话)
  • 若是是 POINT_UP ,从 TouchTargets 中清除 POINTER 信息;若是 UP 或者 CANCEL 重置状态

六.TouchTarget

  • 做用: 记录单view是被哪些 pointer(手指)按下的
  • 结构: 单向链表

七.面试题分享

Alibaba 面试题: 有一个 ViewGroup, 而后手指头接触 Button ,手指头滑开了,滑开又松手的过程,整个事件发生了什么?经历了什么?

  一开始ViewGroup 会接受到整个事件序列的第一个事件: ACTION_DOWNViewGroup#dispatchTouchEvent 收到ACTION_DOWN 后,

  开始询问 ViewGroup#onInterceptTouchEvent 是否须要拦截,

  默认状况下 ViewGroup#onInterceptTouchEvent 返回false 不拦截,开始向下传递ACTION_DOWN 事件,

  Buttton#dispatchTouchEvent 收到ACTION_DOWN 询问onTouchEvent 是否处理,

  Button 默认处理,此后的全部事件序列都直接跨过 ViewGroup#onInterceptTouchEvent 的判断直接传递给Button

  但 ViewGroup#dispatchTouchEvent 会收到全部事件。随着手指的滑动Button 的坐标发生了改变,当手指抬起时触发 Button#onClick 事件。

八.参考资料

相关文章
相关标签/搜索