看了N篇事件传递机制的文章博客,用到的时候有些地方依然记不太清,不如自己动手。为了简单明了。没写那么多事。既当做自己的总结也当做笔记。go!
此Demo首先自定义了两个继承LinearLayout的ViewGroup,MyViewGroupA和MyViewGroupB.。一个继承View的MyView。MyViewGroupA 包裹MyViewGroupB 包裹MyView。详细可见代码。Demo下载
(1)MyViewGroupA
package com.dyk.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;
public class MyViewGroupA extends LinearLayout {
public static final String TAG = "MainActivity";
private static final String myViewGroupAContent = "MyViewGroupA";
private Paint mPaint;
public MyViewGroupA(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
public MyViewGroupA(Context context) {
this(context, null);
}
private void initView(Context context) {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.FILL);
mPaint.setTextSize(50f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(myViewGroupAContent, 20, 50, mPaint);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i(TAG, "MyViewGroupA dispatchTouchEvent action:" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG,
"MyViewGroupA onInterceptTouchEvent action:" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "MyViewGroupA onTouchEvent action:" + event.getAction());
return super.onTouchEvent(event);
}
}
(2)
MyViewGroupB
package com.dyk.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
public class MyViewGroupB extends LinearLayout {
public static final String TAG = "MainActivity";
private static final String myViewGroupBContent="MyViewGroupB";
private Paint mPaint;
public MyViewGroupB(Context context) {
this(context,null);
}
public MyViewGroupB(Context context, AttributeSet attrs) {
super(context, attrs);
initView(context);
}
private void initView(Context context) {
mPaint = new Paint();
mPaint.setColor(Color.BLACK);
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.FILL);
mPaint.setTextSize(50f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText(myViewGroupBContent, 20, 50, mPaint);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i(TAG, "MyViewGroupB dispatchTouchEvent action:" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.i(TAG,
"MyViewGroupB onInterceptTouchEvent action:" + ev.getAction());
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "MyViewGroupB onTouchEvent action:" + event.getAction());
return super.onTouchEvent(event);
}
}
(3)MyView
package com.dyk.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class MyView extends View {
public static final String TAG = "MainActivity";
private static final String myViewContent="MyView";
private Paint mPaint;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView(context);
}
private void initView(Context context) {
mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
mPaint.setStyle(Style.FILL);
mPaint.setTextSize(50f);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect rect = new Rect(0, 0, getWidth(), getHeight());
canvas.drawRect(rect, mPaint);
mPaint.setColor(Color.BLACK);
canvas.drawText(myViewContent,20,50, mPaint);
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.i(TAG, "MyView dispatchTouchEvent action:" + event.getAction());
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "MyView onTouchEvent action:" + event.getAction());
return super.onTouchEvent(event);
}
}
(4)activity_main布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#aaa"
android:orientation="vertical" >
<com.dyk.view.MyViewGroupA
android:id="@+id/myViewGroupA"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff0000" >
<com.dyk.view.MyViewGroupB
android:id="@+id/myViewGroupB"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="50dp"
android:background="#00ff00"
android:padding="50dp" >
<com.dyk.view.MyView
android:id="@+id/myView"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.dyk.view.MyView>
</com.dyk.view.MyViewGroupB>
</com.dyk.view.MyViewGroupA>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="mainActivity unUse place" />
</LinearLayout>
(4)MainActivity
package com.dyk.touchevent;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
public class MainActivity extends Activity {
public static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Log.i(TAG, "MainActivity dispatchTouchEvent action:" + ev.getAction());
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.i(TAG, "MainActivity onTouchEvent action:" + event.getAction());
return super.onTouchEvent(event);
}
}
Activity有dispatchTouchEvent ()和onTouchEvent()方法,ViewGroup有 dispatchTouchEvent ()、onInterceptTouchEvent()和onTouchEvent()方法。其中onInterceptTouchEvent()为
拦截核心方法。View有dispatchTouchEvent ()和onTouchEvent()方法。dispatchTouchEvent()优先级大于onInterceptTouchEvent ()大于onTouchEvent ()。
没有更改任何返回值,正常情况:
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
2)单击MyViewGroupB : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
3)单击MyView : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyView dispatchTouchEvent action:0 ---->
MyView onTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
4)单击MainActivity : MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
注:action:0代表MotionEvent.ACTION_DOWN,action:1
代表MotionEvent.ACTION_UP。
有关修改Activity:
仅修改MainActivity中的dispatchTouchEvent()方法,使其返回值为true。可以发现,不论点击MyViewGroupA 、MyViewGroupB、MyView还是MainActivity的空白区域log输出都如下:
MainActivity dispatchTouchEvent action:0---->
MainActivity dispatchTouchEvent action:1---->
仅修改MainActivity中的onTouchEvent()方法,使其返回值为true。因为MainActivity中的onTouchEvent()方法总是最后执行,所以看起来效果和
正常情况效果一样,
注:只是看起来一样。
有关修改MyViewGroupA:
仅修改MyViewGroupA的
dispatchTouchEvent()方法,使其返回值为true。
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1.
2)单击MyViewGroupB : 和单击MyViewGroupA效果一样
3)单击MyView : 和单击MyViewGroupA效果一样
4)单击MainActivity : MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
仅修改MyViewGroupA的
onInterceptTouchEvent()方法,使其返回值为true。
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
2)单击MyViewGroupB : 和单击MyViewGroupA效果一样
3)单击MyView : 和单击MyViewGroupA效果一样
4)单击MainActivity : MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
仅修改MyViewGroupA的
onTouchEvent ()方法,使其返回值为true。
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1---->
MyViewGroupA onTouchEvent action:1
2)单击MyViewGroupB : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1---->
MyViewGroupA onTouchEvent action:1
3)单击MyView : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyView dispatchTouchEvent action:0 ---->
MyView onTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1---->
MyViewGroupA onTouchEvent action:1
4)单击MainActivity : MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
有关修改MyView:
仅修改MyView的
dispatchTouchEvent
()方法,使其返回值为true。
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
2)单击MyViewGroupB : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
3)单击MyView : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyView dispatchTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1 ---->
MyViewGroupA onInterceptTouchEvent action:1 ---->
MyViewGroupB dispatchTouchEvent action:1 ---->
MyViewGroupB onInterceptTouchEvent action:1 ---->
MyView dispatchTouchEvent action:1 ---->
4)单击MainActivity: MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
仅修改MyView的
onTouchEvent
()方法,使其返回值为true。
1)单击MyViewGroupA : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
2)单击MyViewGroupB : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyViewGroupB onTouchEvent action:0 ---->
MyViewGroupA onTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onTouchEvent action:1 .
3)单击MyView : MainActivity dispatchTouchEvent action:0---->
MyViewGroupA dispatchTouchEvent action:0 ---->
MyViewGroupA onInterceptTouchEvent action:0 ---->
MyViewGroupB dispatchTouchEvent action:0 ---->
MyViewGroupB onInterceptTouchEvent action:0 ---->
MyView dispatchTouchEvent action:0 ---->
MyView onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MyViewGroupA dispatchTouchEvent action:1 ---->
MyViewGroupA onInterceptTouchEvent action:1 ---->
MyViewGroupB dispatchTouchEvent action:1 ---->
MyViewGroupB onInterceptTouchEvent action:1 ---->
MyView dispatchTouchEvent action:1 ---->
MyView onTouchEvent action:1
4)单击MainActivity : MainActivity dispatchTouchEvent action:0---->
MainActivity onTouchEvent action:0 ---->
MainActivity dispatchTouchEvent action:1---->
MainActivity onT ouchEvent action:1 .
事件传递(dispatchTouchEvent、onInterceptTouchEvent)的顺序是:MainActivity---->MyViewGroupA---->MyViewGroupB---->MyView
事件处理(onTouchEvent)的顺序是:MyView---->MyViewGroupB---->MyViewGroupA---->MainActivity
事件传递的返回值:true:拦截、不继续。false : 不拦截、继续。
事件处理的返回值:true:处理了,不用调用下级的onTouchEvent()。false : 没有处理,需要调用上级的onTouchEvent() 。