Android Touch 事件传递机制

转载请注明出处:http://blog.csdn.net/fishle123/article/details/50638795

在 Android UI 开发中,经常涉及touch(触摸)事件和手势最经常使用的点击事件(OnClickListener)也与 touch 事件相关。因此,理解 touch 事件在 View 层级中的传递机制尤为重要。然而,dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent等一系列接口方法很容易让人混淆。

本文将介绍 touch 事件的一些基础知识,并通过分析 Android FrameWork 源码来深入理解 touch 事件的分发机制。

MotionEvent与事件分发相关的方法

1.MotionEvent 

MotionEvent类封装了一个 Touch 事件的相关参数,我们通常所说的一个 Touch 事件,就是通过MotionEvent类的实例来描述。一个 MotionEvent 可以分为多种类型,即 ACTION_DOWN(按下)、ACTION_MOVE(移动)、ACTION_UP(抬起)和 ACTION_CANCEL(取消)等。

1)ACTION_DOWN:

一般来说,通常的 Touch 事件触发的流程都是 DOWN -->UP,或者 DOWN -->MOVE-->...-->MOVE--> UP。所以 ACTION_DOWN 事件通常都是一系列连续操作事件的起点,MOVE事件是否能够被触发取决于操作手势里面是否包含了移动的动作。

2)ACTION_MOVE:

当手指按下后在屏幕上移动,就会产生 ACTION_MOVE 事件,并且通常会随着手指移动而连续产生很多个。

3)ACTION_UP:

UP 是一系列手势操作的结束点,程序会在收到 ACTION_UP 事件时做一些收尾性的工作,例如恢复 View 的点击状态,值得一提的是,View 的 onClick 方法就是在 ACTION_UP 时加以判断满足其他条件之后被触发的。

4)ACTION_CANCEL:

CANCEL 事件不是由用户触发的,而是系统经过逻辑判断后对某个 View 发送“取消”消息时产生的。收到 CANCEL 事件时,View 应该负责将自己的状态恢复。

2.事件分发方法

 public boolean dispatchTouchEvent(MotionEvent ev):

事件由上一层的 View 传递到下一层 View 的过程称为事件分发。dispatchTouchEvent 方法负责事件分发。Activity、ViewGroup、View 类中都定义了该方法,所以它们都具有事件分发的能力。

Activity.dispatchTouchEvent 实际上是调用了 DecorView 的 dispatchTouchEvent 方法,而 DecorView 实际上是一个 FrameLayout,因此,Activity 的 dispatchTouchEvent 最终也是调用到了 ViewGroup 的 dispatchTouchEvent 方法。

另外,由于 View 没有管理子 View 的能力,所以 View.dispatchTouchEvent 方法实际上不是用来向下分发事件,而是将事件分发给自己,调用了自己的事件响应方法去响应事件。

3.事件拦截

public boolean onInterceptTouchEvent(MotonEvent event)

事件在 ViewGroup 的分发过程中,ViewGroup 可以决定是否拦截事件而不对子 View 分发。该方法的返回值决定是否需要拦截的,返回 true 表示拦截,false 表示不拦截。该方法只定义在 ViewGroup 类中.

4.事件响应方法 

public boolean onTouchEvent(MotionEvent event):

该方法负责响应事件,并且返回一个 boolean 型,表示是否消费掉事件,返回 true 表示消费,false 表示不消费。Activity、View、ViewGroup 都有这个方法,所以它们都具有事件响应的能力,并且通过返回值来表示事件是否已经消费。如果子View没有消费掉Touch事件,那么会传递给上一层的View来处理。

消息分发流程,从上到下,从父到子:Activity->ViewGroup1->ViewGroup1的子ViewGroup2->…->Target View
消息响应流程,从下到上,从子到父:Target View->…->ViewGroup1的子ViewGroup2->ViewGroup1->Activity

、View 中 Touch 事件的分发逻辑

先来看 一下View.dispatchTouchEvent 的源码:

/**
     * Pass the touch screen motion event down to the target view, or this
     * view if it is the target.
     *
     * @param event The motion event to be dispatched.
     * @return True if the event was handled by the view, false otherwise.
     */
    public boolean dispatchTouchEvent(MotionEvent event) {
        boolean result = false;
 
        if (mInputEventConsistencyVerifier != null) {
            mInputEventConsistencyVerifier.onTouchEvent(event, 0);
        }
 
        final int actionMasked = event.getActionMasked();
        if (actionMasked == MotionEvent.ACTION_DOWN) {
            // Defensive cleanup for new gesture
            stopNestedScroll();
        }
 
        if (onFilterTouchEventForSecurity(event)) {
            //noinspection SimplifiableIfStatement
            ListenerInfo li = mListenerInfo;
 
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    && li.mOnTouchListener.onTouch(this, event)) {
             //只要view设置了OnTouchListerner并且enable了,那么就调用OnTouchListener.onTouch来处理
                result = true;
            }
             //如果view没有设置OnTouchListener或者OnTouchListener.onTouch返回false(表明没有消费该Touch事件),那么调用View的onTouchEvent来处理
            if (!result && onTouchEve
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值