Android Touch事件分发和消费机制

本文详细解析了Android中Touch事件的分发和消费机制,包括按下、移动、取消和离开四个基本事件。从Activity开始,事件经过View和ViewGroup的dispatchTouchEvent与onTouchEvent方法进行处理和分发。文中探讨了View如何判断和控制事件分发,以及ViewGroup如何寻找目标子View并处理事件。此外,还提到了安全检测、使能状态检查以及TouchDelegate在事件处理中的作用。
摘要由CSDN通过智能技术生成

概述

Touch事件分发和消费机制是指用户用手操作手机屏幕时所造成的事件触发,最基本的包括以下四种:
- 按下Down
- 移动Move
- 取消Cancel
- 离开触摸屏Up
一个完整的Touch过程一般是由Down->(Move)->Up/Cancel这四个事件组成,值得注意的是,一个完整的触摸事件必须由Down开始,再到Up/Cancel结束,中间的Move可以有可以没有。
Touch事件还有很多,这四个是最基础的。

总体流程

一个Touch事件的触发,必须经由Activity向下分发,最终到达接受的View进行消费处理。由Activity开始分发,如果ViewGroup在子View中找到可以处理该事件的View,则继续向下传递,否则ViewGroup会尝试消费处理该事件。

View对Touch事件的处理过程

首先来看View怎么处理Touch事件。

dispatchTouchEvent

//最主要的触摸事件的分发逻辑,向接收Touch事件的子View(包括自己)派发事件,对于View而非ViewGroup来说,这里只会对自己分发。
boolean dispatchTouchEvent(MotionEvent event);

这个方法用来判断和控制事件的分发,也就是说不论该View是否对Touch事件响应,都要触发这个方法。只有触发这个方法,才能确实事件究竟是消费还是继续向下分发。

来看一下部分源码分析。

public boolean dispatchTouchEvent(MotionEvent event) {
    boolean result = false;
    //1.停止嵌套滑动
    final int actionMasked = event.getActionMasked();
    if (actionMasked == MotionEvent.ACTION_DOWN) {
        stopNestedScroll();
    }
    //2.安全监测
    if (onFilterTouchEventForSecurity(event)) {
        //noinspection SimplifiableIfStatement
        ListenerInfo li = mListenerInfo;

        //3.如果当前View使能(setEnabled(true)),则调用Touch监听器    
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnTouchListener.onTouch(this, event)) {
            result = true;
        }
        //4.如果Touch监听器返回false或者没有调用Touch监听器,则返回调用onTouchEvent()
        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }
    //停止嵌套滑动
    if (actionMasked == MotionEvent.ACTION_UP ||
            actionMasked == MotionEvent.ACTION_CANCEL ||
            (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
        stopNestedScroll();
    }

    return result;
}

首先可以看到,该方法会返回一个boolean值,用来判断事件是否继续向下分发。如果boolean值为true,则表明事件被消费;如果为false,则表明事件没有被这个View消费,继续向下分发。

流程
在dispatchTouchEvent一开始,就定义了一个result变量,并在最后返回。当result返回为false时,表明事件没有被这个View处理,继续分发;如果返回为true,则表明事件已经被这个View消费处理。
1. 先暂时停止嵌套滑动,开始对事件进行分析
2. 安全检测:如果view通过setFilterTouchesWhenObscured(true)方法设置了安全检测,那在此处就会做出判断。
- 安全检测:官方给出的解释是:

Specifies whether to filter touches when the view’s window is obscured by another visible window.
意思是说,指定当一个窗体显示的时候(获取焦点),是否隐藏该view的响应。

也就是说,如果我们的view被设置setFilterTouchesWhenObscured(true)或者android:filterTouchesWhenObscured的话,当另外一个窗体显示的时候,我们的view不响应任何事件。

注:

/**     
* Filter the touch event to apply security policies. 过滤触摸事件应用安全策略     
*     
* @param event The motion event to be filtered. 
* @return True if the event should be dispatched, false if the event should be dropped.如果是True的话就向下传递,否则就跳出触摸事件     
* @see #getFilterTouchesWhenObscured     
*/    
public 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值