原标题: Mastering the Android Touch System
原文地址: speakerd.s3.amazonaws.com
原文作者: Dave Smith
如何处理 Andriod 触摸事件
所有的 Touch 事件都封装为 MotionEvent 对象,包括触摸的位置,多点触控和事件发生的时间。 事件的基础类型分为 ACTION_DOWN ACTION_UP ACTION_MOVE ACTION_POINTER_DOWN ACTION_POINTER_UP ACTION_CANCEL,并且每个事件都是从 ACTION_DOWN 开始到 ACTION_UP 结束 。对事件的处理包括三类,分别为传递——dispatchTouchEvent() 函数、拦截——onInterceptTouchEvent()函数、消费——onTouchEvent() 函数和 OnTouchListener
事件传递的流程
事件从 Activity.dispatchTouchEvent() 开始传递,如果事件在传递的过程中没有被消费,会从最上层的父视图(ViewGroup) 开始按照从上而下的顺序传递事件直到该事件被消费,在传递的过程中子视图可以随时消耗事件,如果父视图消费了 ACTION_DOWN 事件,之后的其他事件将不会继续传递到子视图处理。任何未消耗的事件都会传递到 Activity 的 onTouchEvent() 后结束。如果还是没有被消费的话,则会返回到 Activity 的 onTouchEvent() 函数,可以通过对外的 OnTouchListener 来消费 View/ViewGroup 的任意事件,如果 View.dispatchTouchEvent() 存在的话会将事件交由 View.OnTouchListener.onTouch() 处理,如果事件没有被消费则其自身来负责事件流程。
如果在 ViewGroup.dispatchTouchEvent() 的事件传递过程中,如果父视图的 onInterceptTouchEvent() 中消费了事件则子视图的 onInterceptTouchEvent() 不会在接收到任何的事件,直接由父视图自己进行处理。对于每个子视图会以相反的顺序添加它们,如果在之前没有进行处理,则交由子级的视图进行消费触摸事件。
事件拦截的时候在 onInterceptTouchEvent() 函数返回一个 true,子视图会收到一个 ACTION_CANCEL 事件后则认为该事件已经结束,不在执行下一步的处理,而接下来收到的所有事件则返回 ViewGroup 来进行处理。当然子视图可以调用 requestDisallowTouchIntercept() 来阻碍父视图的 onInterceptTouchEvent() 对当前所滑动的手势进行拦截。
错误的视图案例
有趣的视图案例
处理事件
子类重写 onTouchEvent() 方法,并提供一个 OnTouchListener。使用 ACTION_DOWN 并返回 true 表示消耗该事件即使您对 ACTION_DOWN不大算消耗该事件也请返回 true,对于其他事件,返回 true 会停止事件的进一步处理。
在 ViewConfiguration 中有用的常量:
getScaledTouchSlop():移动距离的事件可能会在其拖动之前就会发生变化getScaledMinimumFlingVelocity():系统认为快速滑动是一种惯性拖拽getScaledPagingTouchSlop():事件池使用一个水平分页手势(i.e. ViewPager)
以上内容是 Mastering the Android Touch System PPT 1-10页的内容总结,文章有些术语及方法释明需要调整校对。剩下的10页会陆续补上。如果有不妥的地方,欢迎大家提出,一起完善。