事件分发,事件拦截,事件消费

本文详细解析了Android中事件处理机制,包括事件的构成、View与ViewGroup中的关键事件处理方法及其调用顺序,并通过实例代码展示了事件如何在多层布局间传递及被不同组件拦截与消费的过程。

一、 Android 中事件的构成

在Android中,事件主要包括点按、长按、拖拽、滑动等,点按又包括单击和双击,另外还包括单指操作和多指操作。所有这些都构成了Android中的事件响应。

总的来说,所有的事件都由如下三个部分作为基础:

按下(ACTION_DOWN)

移动(ACTION_MOVE)

抬起(ACTION_UP)

所有的操作事件首先必须执行的是按下操作(ACTION_DOWN),之后所有的操作都是以按下操作作为前提,当按下操作完成后,接下来可能是一段移动(ACTION_MOVE)然后抬起(ACTION_UP),或者是按下操作执行完成后没有移动就直接抬起。这一系列的动作在Android中都可以进行控制。


二、 View 中与事件关联的三个方法

我们知道,所有的事件操作都发生在触摸屏上,而在屏幕上与我们交互的就是各种各样的视图组件(View),在Android中,所有的视图都继承于View,另外通过各种布局组件(ViewGroup)来对View进行布局,ViewGroup也继承于View。所有的UI控件例如Button、TextView都是继承于View,而所有的布局控件例如RelativeLayout、容器控件例如ListView都是继承于ViewGroup。所以,我们的事件操作主要就是发生在View和ViewGroup之间,那么View和ViewGroup中主要有哪些方法来对这些事件进行响应呢?

记住如下3个方法,我们通过查看View和ViewGroup的源码可以看到:


873202.png

Activity跟View类似,也没有onInterceptTouchEvent,有其他两个


在View和ViewGroup中都存在dispatchTouchEvent和onTouchEvent方法,但是在ViewGroup中还有一个onInterceptTouchEvent方法。

在Android中,所有的事件都是从开始经过传递到完成事件的消费,这些方法的返回值就决定了某一事件是否是继续往下传,还是被拦截了,或是被消费了。这些方法决定了整个事件到底该怎么传递。

这些方法的参数,都接受了一个MotionEvent类型的参数,MotionEvent继承于InputEvent,用于标记各种动作事件。之前提到的ACTION_DOWN、ACTION_MOVE、ACTION_UP都是MotinEvent中定义的常量。我们通过MotionEvent传进来的事件类型来判断接收的是哪一种类型的事件。到现在,这三个方法的返回值和参数你应该都明白了,接下来就解释一下这三个方法分别在什么时候处理事件。



三、ViewGroup(View,activity)中三(两个)个处理事件方法的调用顺序

先调用dispatchTouchEvent分发事件,dispatchTouchEvent会调用onInterceptTouchEvent判断是否拦截事件,然后dispatchTouchEvent根据onInterceptTouchEvent的结果,判断是否需要调用onTouchEvent处理事件或继续让子控件分发事件(所有ViewGroup都适用,View没有onInterceptTouchEvent,另外两个调用顺序一样

package com.example.zhouyi.eventtest;

/**
 * Created by zhouyi on 16/7/13.
 */
public class EventUtils {

    public static String getEvent(int iCode){
        switch (iCode){
            case 0:
                return "down";
            case 1:
                return "up";
            case 2:
                return "move";
}
        return "null";
}

}

package com.example.zhouyi.eventtest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class MyTop1Layout extends RelativeLayout {
    public MyTop1Layout(Context context) {
        super(context);
}

    public MyTop1Layout(Context context, AttributeSet attrs) {
        super(context, attrs);
}

    public MyTop1Layout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {

        Log.d("qf", "MyTop1Layout.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));
        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MyTop1Layout.dispatchTouchEvent.返回值:"+bRet);
        return bRet;

}

    @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("qf", "MyTop1Layout.onInterceptTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));

        boolean bRet = super.onInterceptTouchEvent(ev);
Log.d("qf","MyTop1Layout.onInterceptTouchEvent.返回值:"+bRet);

        return bRet;
}

    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MyTop1Layout.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));

        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MyTop1Layout.onTouchEvent.返回值:"+bRet);


        return bRet;
}


}


<?xml version="1.0" encoding="utf-8"?>
<com.example.zhouyi.eventtest.MyTop1Layout 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"
tools:context="com.example.zhouyi.eventtest.MainActivity">

</com.example.zhouyi.eventtest.MyTop1Layout>

点击界面,查看日志打印


07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:down
07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:down
07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onTouchEvent.发生事件:down
07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onTouchEvent.返回值:false
07-13 14:32:12.200 29240-29240/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:false





四、多层布局嵌套时,事件处理的顺序和返回值的意义
package com.example.zhouyi.eventtest;

/**
 * Created by zhouyi on 16/7/13.
 */
public class EventUtils {

    public static String getEvent(int iCode){
        switch (iCode){
            case 0:
                return "down";
            case 1:
                return "up";
            case 2:
                return "move";
}
        return "null";
}

}

package com.example.zhouyi.eventtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;

public class MainActivity extends AppCompatActivity {

    @Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("qf", "MainActivity.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));
        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MainActivity.dispatchTouchEvent.返回值:"+bRet);
        return bRet;
}

    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MainActivity.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));

        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MainActivity.onTouchEvent.返回值:"+bRet);


        return bRet;
}


}
package com.example.zhouyi.eventtest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class MyTop1Layout extends RelativeLayout {
    public MyTop1Layout(Context context) {
        super(context);
}

    public MyTop1Layout(Context context, AttributeSet attrs) {
        super(context, attrs);
}

    public MyTop1Layout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {

        Log.d("qf", "MyTop1Layout.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));
        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MyTop1Layout.dispatchTouchEvent.返回值:"+bRet);
        return bRet;

}

    @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("qf", "MyTop1Layout.onInterceptTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));

        boolean bRet = super.onInterceptTouchEvent(ev);
Log.d("qf","MyTop1Layout.onInterceptTouchEvent.返回值:"+bRet);

        return bRet;
}

    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MyTop1Layout.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));

        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MyTop1Layout.onTouchEvent.返回值:"+bRet);


        return bRet;
}


}

package com.example.zhouyi.eventtest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.RelativeLayout;

public class MyTop2Layout extends RelativeLayout {
    public MyTop2Layout(Context context) {
        super(context);
}

    public MyTop2Layout(Context context, AttributeSet attrs) {
        super(context, attrs);
}

    public MyTop2Layout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {

        Log.d("qf", "MyTop2Layout.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));

        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MyTop2Layout.dispatchTouchEvent.返回值:"+bRet);
        return bRet;

}

    @Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.d("qf", "MyTop2Layout.onInterceptTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));

        boolean bRet = super.onInterceptTouchEvent(ev);
Log.d("qf","MyTop2Layout.onInterceptTouchEvent.返回值:"+bRet);

        return bRet;
}

    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MyTop2Layout.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));

        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MyTop2Layout.onTouchEvent.返回值:"+bRet);

        return bRet;
}
}

package com.example.zhouyi.eventtest;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;

public class MyButton extends Button {
    public MyButton(Context context) {
        super(context);
}

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
}

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {

        Log.d("qf", "MyButton.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));
        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MyButton.dispatchTouchEvent.返回值:"+bRet);
        return bRet;

}


    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MyButton.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));
        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MyButton.onTouchEvent.返回值:"+bRet);

        return bRet;
}
}

<?xml version="1.0" encoding="utf-8"?>
<com.example.zhouyi.eventtest.MyTop1Layout 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"
tools:context="com.example.zhouyi.eventtest.MainActivity">

    <com.example.zhouyi.eventtest.MyTop2Layout
android:layout_width="match_parent"
android:layout_height="match_parent">

        <com.example.zhouyi.eventtest.MyButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试"
/>



    </com.example.zhouyi.eventtest.MyTop2Layout>

</com.example.zhouyi.eventtest.MyTop1Layout>

点击按钮,打印:
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.发生事件:down
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.返回值:true
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.返回值:true
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.返回值:true
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:true
07-13 15:11:21.968 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.返回值:true
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.发生事件:move
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.返回值:true
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.返回值:true
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.返回值:true
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:true
07-13 15:11:21.992 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.返回值:true
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.返回值:false
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.发生事件:up
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.返回值:true
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.返回值:true
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.返回值:true
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:true
07-13 15:11:22.056 30325-30325/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.返回值:true


返回值的意义:
  • dispatchTouchEvent返回true,表示在本层view或者本层view的所有下级view中,有view处理完了这个事件(onTouchEvent返回了true)—上例中,最终是button的onTouchEvent返回了true,所以所有dispatchTouchEvent都返回了true
  • dispatchTouchEvent返回fasle,表示在本层view或者本层view的所有下级view中,没有view处理完了这个事件(onTouchEvent都返回了false)—上例中,把button的onTouchEvent返回值改成false,再看结果,验证这个规则(所有的dispatch都返回了false)
  • onInterceptTouchEvent返回false,表示本层view不拦截这个事件,交给下一层view去处理—上例中,button之上所有view的onInterceptTouchEvent都返回false,所以最终由button来处理事件(button是一个view,没有onInterceptTouchEvent方法,只要它的父控件没有拦截事件,就会调用button的onTouchEvent)
  • onInterceptTouchEvent返回true,表示本层view拦截了这个事件,这个事件不会再往下传递了,而是交给本层的ontouchevent处理(调用本层view的ontouchevent)—上例中,把top1或top2layout的onInterceptTouchEvent的返回值改为true验证一下(返回true的那一层的ontouchevent调用了)
  • onTouchEvent返回true表示已经处理完这个事件了,不需要父控件再处理了—比如上例中,只有button调用了onTouchEvent
  • onTouchEvent返回false表示还没有处理完这个事件,传给父控件继续处理,直到某一层父控件的onTouchEvent返回了true(或调用完activity的onTouchEvent,这时再也没法上溯了)—上例中把button的onTouchEvent返回值改成false,查看结果(所有层级的onTouchEvent都调用了)

事件分发和拦截--隧道式
  • 事件从父布局(activity开始)开始分发,如果本级别view没有拦截(onInterceptTouchEvent返回false),一直分发到直接感应触摸的控件(或布局),如果在某个级别的view拦截了事件(onInterceptTouchEvent返回true),不管本级别有没有消费这个事件(onTouchEvent的返回值),都不会再让其子view分发事件了(其子view的所有事件方法都不会调用了)—上例中top2layout的拦截返回true,则button的事件方法都不会调用了
down事件的处理(消费)—冒泡式
  • ViewGroup的事件被拦截,或者View的事件没有被父控件拦截,都会调用本view(或ViewGroup)的事件处理方法(onTouchEvent),这个方法执行完毕后,如果返回true,表示已经处理完,不会让父控件再处理,如果返回false,则会让父控件再处理(调用父控件的onTouchEvent),一直到某个级别的父控件的onTouchEvent返回true为止,或调用完activity的onTouchEvent为止
move和up事件的处理(消费)
  • down事件在哪个级别的view消费的,则后续的up事件也会在那个级别的view上消费(调用那个级别的onTouchEvent),如果那个级别是一个ViewGroup,那个级别的onInterceptTouchEvent不会调用了,那个级别的dispatch还会调用,那个级别之上的父view的onInterceptTouchEvent和dispatch都还照样调用
练习:
上例中,修改top1或top2layout的dispatch返回值,预测下结果,验证下你的预测,思考下为什么


五、事件监听方法和事件处理方法的关系和优先级
除了在view里面的事件处理外,在view外面也可以监听并处理事件,比如上例中,我们可以对button做两个事件监听



package com.example.zhouyi.eventtest;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MainActivity extends AppCompatActivity {
    
    MyButton mBtnTest;

@Override
protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mBtnTest = (MyButton) findViewById(R.id.btntest);

 mBtnTest.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                
            }
        });
        
        mBtnTest.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return false;
            }
        });

}

    @Override
public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("qf", "MainActivity.dispatchTouchEvent.发生事件:"+ EventUtils.getEvent(ev.getAction()));
        boolean bRet = super.dispatchTouchEvent(ev);
Log.d("qf","MainActivity.dispatchTouchEvent.返回值:"+bRet);
        return bRet;
}

    @Override
public boolean onTouchEvent(MotionEvent event) {
        Log.d("qf", "MainActivity.onTouchEvent.发生事件:"+ EventUtils.getEvent(event.getAction()));

        boolean bRet = super.onTouchEvent(event);
Log.d("qf","MainActivity.onTouchEvent.返回值:"+bRet);


        return bRet;
}


}

加上日志打印:
mBtnTest.setOnClickListener(new View.OnClickListener() {
    @Override
public void onClick(View v) {
        Log.d("qf","MyButton.onClick");
}
});

mBtnTest.setOnTouchListener(new View.OnTouchListener() {
    @Override
public boolean onTouch(View v, MotionEvent event) {
        Log.d("qf","MyButton.onTouch");
        return false;
}
});

最终日志:
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.返回值:false
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouch
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.发生事件:down
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.返回值:true
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.返回值:true
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.返回值:true
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:false
07-13 16:24:50.303 22665-22665/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.返回值:true
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.onInterceptTouchEvent.返回值:false
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.onInterceptTouchEvent.返回值:false
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouch
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.发生事件:up
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onTouchEvent.返回值:true
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.dispatchTouchEvent.返回值:true
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop2Layout.dispatchTouchEvent.返回值:true
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyTop1Layout.dispatchTouchEvent.返回值:false
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MainActivity.dispatchTouchEvent.返回值:true
07-13 16:24:50.391 22665-22665/com.example.zhouyi.eventtest D/qf: MyButton.onClick

首先调用了MyButton.dispatchTouchEvent,然后调用了MyButton.onTouch,然后是MyButton.onTouchEvent,最后在up事件后调用MyButton.onClick

修改View.OnTouchListener的onTouch返回值为true,查看结果—不会再调用MyButton.onTouchEvent和MyButton.onClick,因为返回值为true表示已经消费完这个事件了,MyButton.dispatchTouchEvent依然还是返回true

六、


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值