概述
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