看了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() 。