Android事件处理机制
Android事件处理机制更准确的说应该叫 “Android事件分发、拦截、处理机制”。这里主要是针对Android中dispatchTouchEvent(分发TouchEvent), onInterceptTouchEvent(拦截TouchEvent), onTouchEvent(处理TouchEvent)事件的理解.
首先我们来认识下dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent事件.
dispatchTouchEvent用于决定事件是否分发,当TouchEvent事件发生时,最先到达顶层Activity的dispatchTouchEvent方法,返回ture或false时事件被自身消费处理,返回super.dispatchTouchEvent(ev)(后面简称super)传递给下一层级dispatchTouchEvent方法处理.
onInterceptTouchEvent用于决定事件是否继续向下传递返回false或super时事件会传递给子View,返回值为true时事件不会继续传递给子View,事件将交给当前ViewGroup的onTouchEvent()处理,这就是所谓的Intercept(拦截)。
onTouchEvent用于处理事件(传递方向是从子View->父View),返回值决定当前控件是否消费(处理)了这个事件。返回值为true表示处理了当前事件,父View的OnTouchEvent事件将不会执行,返回值为false或super表示不处理当前事件交给父View的OnTouchEvent事件处理。
注:对于当前事件理解: 一次点击操作可能包含三个事件,按下事件(Down),移动事件(Move),弹起事件(up).
对于ACTION_DOWN事件,返回true,表示我想要处理后续事件;返回false,表示不关心此事件,并返回由父类进行处理。
特别注意ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN,如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过,所以ACTION_MOVE或者ACTION_UP就不能被捕获。
我们看下示例:
布局如下
[java]<?xml version="1.0" encoding="utf-8"?>
<com.scxh.android1502.event.RootLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.scxh.android1502.event.TwotLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.scxh.android1502.event.ChildTextView
android:id="@+id/event_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="android事件处理机制" />
</com.scxh.android1502.event.TwotLayout>
</com.scxh.android1502.event.RootLayout>[/java]
测试代码
[java]public class RootLayout extends LinearLayout {
public RootLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Logs.d("RootLayout onInterceptTouchEvent >>>>>>>");
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
Logs.i("RootLayout onTouchEvent 事件 ACTION_UP>>>>>>>>");
break;
case MotionEvent.ACTION_MOVE:
Logs.v("RootLayout onTouchEvent 事件 ACTION_MOVE>>>>>>>>");
break;
case MotionEvent.ACTION_DOWN:
Logs.d("RootLayout onTouchEvent 事件 ACTION_DOWN>>>>>>>>");
break;
}
return true;
}
}[/java]
[java]public class TwotLayout extends LinearLayout {
public TwotLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Logs.i("TwotLayout onInterceptTouchEvent >>>>>>>");
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
Logs.i("TwotLayout onTouchEvent 事件 ACTION_UP>>>>>>>>");
break;
case MotionEvent.ACTION_MOVE:
Logs.v("TwotLayout onTouchEvent 事件 ACTION_MOVE>>>>>>>>");
break;
case MotionEvent.ACTION_DOWN:
Logs.d("TwotLayout onTouchEvent 事件 ACTION_DOWN>>>>>>>>");
break;
}
return false;
}
}[/java]
[java]
public class ChildTextView extends TextView {
public ChildTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
Logs.i("ChildTextView onTouchEvent 事件 ACTION_UP>>>>>>>>");
break;
case MotionEvent.ACTION_MOVE:
Logs.v("ChildTextView onTouchEvent 事件 ACTION_MOVE>>>>>>>>");
break;
case MotionEvent.ACTION_DOWN:
Logs.d("ChildTextView onTouchEvent 事件 ACTION_DOWN>>>>>>>>");
break;
}
return true;
}
}
[/java]
1. 当RootLayout,TwoLayout的onInterceptTouchEvent事件返回false也就是不拦截且ChildTextView的onTouchEvent事件返回true消耗第一个Action_Down事件执行情况为:


2.当RootLayout,TwoLayout的onInterceptTouchEvent事件返回false也就是不拦截且ChildTextView的onTouchEvent事件返回false不消耗第一个Action_Down事件执行情况为:

事件传输机制更详细理解推荐kelin写的这编文章,http://www.jianshu.com/p/e99b5e8bd67b
这里贴张图.
参考
细说Android事件传递机制(dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent)
Android-onInterceptTouchEvent()和onTouchEvent()总结
Android中dispatchTouchEvent, onInterceptTouchEvent, onTouchEvent的理解
转载请注明来源:Android事件处理机制






























