android事件传递——1.概述

1 事件传递流程概述

事件的传递是由最顶层(即最外层)的父控件开始,一层一层向下传递,直到最底层(即最内层)的子控件。若最底层的子控件没有消耗掉事件,则:事件又会从最底层的子控件开始,一层一层向上传递,直到最顶层的父控件。

当父控件不拦截事件(onInterceptTouchEvent返回true,代表拦截事件)时,事件才会向下传递给其子控件。含有子view的viewGroup默认都不会拦截。当子控件不消耗掉事件(onTouchEvent返回true,代表消耗掉事件)时,事件才会向上传递给其父控件。

以上为完整的事件传递流程,后面我们将知道,只有down事件会走完整的事件传递流程,move、up等后续事件走的都是简化的事件传递流程。

2 事件传递方法

以ViewGroup为例:

  • public boolean dispatchTouchEvent(MotionEvent ev):管理事件的分发,返回值表示当前控件或其直接、间接的子控件是否消耗了事件。这个返回值代表的是事件分发的结果,并不会左右事件分发的走向。

  • public boolean onInterceptTouchEvent(MotionEvent ev): 在dispatchTouchEvent方法的内部被调用,返回值表示是否要拦截事件。需要注意的是,一旦拦截了某个事件,那么同一事件序列中的后续事件都不会再经过onInterceptTouchEvent。事件序列:从手指按下,经过移动,到手指抬起,这一系列触摸事件称为一个事件序列。

  • public boolean onTouchEvent(MotionEvent ev):处理事件,返回值表示是否消耗当前事件。

以上三个方法的关系可用下面的伪代码来表示:

public boolean dispatchTouchEvent(MotionEvent ev){
    boolean comsume = false;
    if(onInterceptTouchEvent(ev)){//若拦截,则交给自己的onTouchEvent处理
        comsume = onTouchEvent(ev);
    }else{//若不拦截,则交给子view
        comsume = child.dispatchTouchEvent(ev);
    }
    return comsume;
}
//注意:View没有onInterceptTouchEvent方法,一旦有触摸事件传递给它,它的onTouchEvent方法就会被调用

可见,onInterceptTouchEvent和onTouchEvent都是在dispatchTouchEvent中被调用的:

  • 若onInterceptTouchEvent拦截了事件,则将事件交给自己的onTouchEvent处理
  • 若onInterceptTouchEvent未拦截事件,则将事件往下传递给子view的dispatchTouchEvent

在dispatchTouchEvent中可以通过调用requestDisallowInterceptTouchEvent来请求所有的父控件不要拦截事件:

public boolean dispatchTouchEvent(MotionEvent ev) {
	getParent().requestDisallowInterceptTouchEvent(true);// 请求所有父控件不要拦截事件
	...
}

效果是所有父控件的onInterceptTouchEvent方法都不会被调用。

发布了46 篇原创文章 · 获赞 38 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/al4fun/article/details/75036633