原标题: 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页会陆续补上。如果有不妥的地方,欢迎大家提出,一起完善。