这几天一直在研究onTouch的相关方法,今天我们就来看看onTouchEvent、dispatchTouchEvent、onIntercepTouchEvent这三个方法在控件之间的传递顺序
public boolean dispatchTouchEvent(MotionEvent ev) //用于事件的分发
public boolean onInterceptTouchEvent(MotionEvent ev) // 用于事件的拦截
public boolean onTouchEvent(MotionEvent ev) //处理事件
先看如下代码
1)xml文件
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.mygestrue.MainActivity" > <com.example.mygestrue.MyLinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.mygestrue.MyLinearLayoutT android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.mygestrue.MyTextView android:id="@+id/tv1" android:layout_width="50dp" android:layout_height="50dp" android:background="#0000ff" android:text="@string/hello_world" /> <com.example.mygestrue.MyTextViewT android:layout_marginTop="50dp" android:layout_width="50dp" android:layout_height="50dp" android:background="#ff0000" android:text="@string/hello_world" /> </com.example.mygestrue.MyLinearLayoutT> </com.example.mygestrue.MyLinearLayout> </RelativeLayout>
2)上面用到的几个自定义的类
MyLinearLayout
package com.example.mygestrue; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; public class MyLinearLayout extends LinearLayout { public MyLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyLinearLayout(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "myll1_ontouchevent"); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub Log.e("123", "myll1_dispatchTouchevent"); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub Log.e("123", "myll1_oninterceptouchevent"); return super.onInterceptTouchEvent(ev); } }
MyLinearLayoutT
package com.example.mygestrue; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; public class MyLinearLayoutT extends LinearLayout { public MyLinearLayoutT(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyLinearLayoutT(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyLinearLayoutT(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "myll2_ontouchevent"); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub Log.e("123", "myll2_dispatchTouchevent"); return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub Log.e("123", "myll2_oninterceptouchevent"); return super.onInterceptTouchEvent(ev); } }
MyTextView
package com.example.mygestrue; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; public class MyTextView extends TextView { public MyTextView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyTextView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyTextView(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "mytv1_ontouchevent"); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "mytv1_dispatchtouchevent"); return super.dispatchTouchEvent(event); } }
MyTextViewT
package com.example.mygestrue; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.TextView; public class MyTextViewT extends TextView { public MyTextViewT(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } public MyTextViewT(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public MyTextViewT(Context context) { super(context); // TODO Auto-generated constructor stub } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "mytv2_ontouchevent"); return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "mytv2_dispatchtouchevent"); return super.dispatchTouchEvent(event); } }
MainActivity
package com.example.mygestrue; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.MotionEvent; public class MainActivity extends ActionBarActivity { ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub Log.e("123", "main_dispatchtouchevent"); return super.dispatchTouchEvent(ev); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. return super.onOptionsItemSelected(item); } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub Log.e("123", "main_ontouchevent"); // return super.onTouchEvent(event); return super.onTouchEvent(event); }; }
1.当我们点击屏幕空白处的时候,打印的log
03-26 13:59:16.879: E/123(6400): main_dispatchtouchevent 03-26 13:59:16.879: E/123(6400): myll1_dispatchTouchevent 03-26 13:59:16.879: E/123(6400): myll1_oninterceptouchevent 03-26 13:59:16.879: E/123(6400): myll2_dispatchTouchevent 03-26 13:59:16.879: E/123(6400): myll2_oninterceptouchevent 03-26 13:59:16.880: E/123(6400): myll2_ontouchevent 03-26 13:59:16.881: E/123(6400): myll1_ontouchevent 03-26 13:59:16.882: E/123(6400): main_ontouchevent 03-26 13:59:17.748: E/123(6400): main_dispatchtouchevent 03-26 13:59:17.748: E/123(6400): myll1_dispatchTouchevent 03-26 13:59:17.748: E/123(6400): myll1_oninterceptouchevent 03-26 13:59:17.749: E/123(6400): myll2_dispatchTouchevent 03-26 13:59:17.749: E/123(6400): myll2_oninterceptouchevent 03-26 13:59:17.749: E/123(6400): myll2_ontouchevent 03-26 13:59:17.749: E/123(6400): myll1_ontouchevent 03-26 13:59:17.751: E/123(6400): main_ontouchevent
得出的结论是
首先是Activity_dispatchTouchEvent->xml最外层容器_dispatchTouchEvent->xml最外层容器_onIntercepTouchEvent->下一层_dispatchTouchEvent->下一层_onIntercepTouchEvent->最末层_onTouchEvent->上一层_onTouchEvent->最外层_onTouchEvent->Activity_onTouchEvent
现在我们更改一下这些touch事件的返回值,如下
activity: dispatchTouchEvent:true onTouchEvent :true linear1: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
打印的log如下
03-26 14:31:32.237: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.267: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.283: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.300: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.317: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.335: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.341: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.914: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.933: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.951: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.968: E/123(6794): main_dispatchtouchevent 03-26 14:31:32.985: E/123(6794): main_dispatchtouchevent 03-26 14:31:33.002: E/123(6794): main_dispatchtouchevent 03-26 14:31:33.006: E/123(6794): main_dispatchtouchevent
只有main_dispatchtouchevent执行了
activity: dispatchTouchEvent:false onTouchEvent :true linear1: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
打印log
03-26 14:35:45.660: E/123(7058): main_dispatchtouchevent 03-26 14:35:45.688: E/123(7058): main_dispatchtouchevent 03-26 14:35:45.706: E/123(7058): main_dispatchtouchevent 03-26 14:35:45.723: E/123(7058): main_dispatchtouchevent 03-26 14:35:45.740: E/123(7058): main_dispatchtouchevent 03-26 14:35:45.748: E/123(7058): main_dispatchtouchevent
还是仅仅执行了main_dispatchtouchevent
activity: dispatchTouchEvent:false onTouchEvent :false linear1: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
打印log
03-26 14:38:26.545: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.563: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.580: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.598: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.615: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.632: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.649: E/123(7223): main_dispatchtouchevent 03-26 14:38:26.650: E/123(7223): main_dispatchtouchevent
结果还是一样:执行的是main_dispatchtouchevent
activity: dispatchTouchEvent:false onTouchEvent :false linear1: dispatchTouchEvent:false onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
打印log
03-26 14:41:04.697: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.722: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.739: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.757: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.774: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.792: E/123(7352): main_dispatchtouchevent 03-26 14:41:04.796: E/123(7352): main_dispatchtouchevent
结果仍然没有改变 main_dispatchtouchevent被执行
activity: dispatchTouchEvent:false onTouchEvent :false linear1: dispatchTouchEvent:false onTouchEvent :true onInterceptTouchEvent:false linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
03-26 14:45:23.294: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.318: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.336: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.353: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.370: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.387: E/123(7487): main_dispatchtouchevent 03-26 14:45:23.390: E/123(7487): main_dispatchtouchevent
好吧,忽然感觉,这个时候,仅仅让activity中的ontouch事件纯粹返回true或者false是没有意义的,这样事件好像根本就没办法往下传了
activity: dispatchTouchEvent:super.dispatchTouchEvent(ev) onTouchEvent :false linear1: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
03-26 14:51:18.871: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.872: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.896: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.897: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.912: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.913: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.929: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.929: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.947: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.948: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.964: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.964: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.978: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.978: E/123(7744): myll1_dispatchTouchevent 03-26 14:51:18.979: E/123(7744): main_dispatchtouchevent 03-26 14:51:18.979: E/123(7744): myll1_dispatchTouchevent
我们看到,这时候,ll1接收到了main_dispatchtouchevent传过来的事件,但是,它并没有继续往下传
activity: dispatchTouchEvent:super.dispatchTouchEvent(ev) onTouchEvent :false linear1: dispatchTouchEvent:false onTouchEvent :true onInterceptTouchEvent:true linear2: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:true tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true
03-26 14:54:58.037: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.037: E/123(7869): myll1_dispatchTouchevent 03-26 14:54:58.039: E/123(7869): main_ontouchevent 03-26 14:54:58.056: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.056: E/123(7869): main_ontouchevent 03-26 14:54:58.073: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.073: E/123(7869): main_ontouchevent 03-26 14:54:58.090: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.090: E/123(7869): main_ontouchevent 03-26 14:54:58.108: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.108: E/123(7869): main_ontouchevent 03-26 14:54:58.122: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.122: E/123(7869): main_ontouchevent 03-26 14:54:58.122: E/123(7869): main_dispatchtouchevent 03-26 14:54:58.123: E/123(7869): main_ontouchevent
我们看到ll1接收到了main_dispatchtouchevent的事件,但是,这时候,ll1的dispatchtouchevent的返回值为false,就是说,这个事件不往下分发,而ll1的interceptouchevent返回值又为true,也就是说,事件拦截,所以它的ontouch就不执行了,这样,就直接执行到了main_touchevent了
activity: dispatchTouchEvent:super.dispatchTouchEvent(ev) onTouchEvent :false linear1: dispatchTouchEvent:true onTouchEvent :true onInterceptTouchEvent:false linear2: dispatchTouchEvent:false onTouchEvent :true onInterceptTouchEvent:false tv1: dispatchTouchEvent:true onTouchEvent :true tv2: dispatchTouchEvent:true onTouchEvent :true