ontouch、dispatchtouchevent、interceptouchevent-相关事件

这几天一直在研究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
原文地址:https://www.cnblogs.com/zhangshuli-1989/p/zhangshuli_touch_150327095.html