android群英传笔记——事件拦截机制(事件分发机制)

事件拦截机制

声明:对事件拦截机制的详细了解,除了群英传上的部分以外,还涵盖了开发艺术探索这本书上的内容,在开发艺术探索这本书上称之为事件分发机制。

什么是事件拦截机制?要了解事件拦截机制,首先要了解触摸事件。

触摸事件就是捕获触摸屏幕后产生的事件,Android为触摸事件封装了一个类——MotionEvent。当点击屏幕通常会产生两或三个事件——按下(MotionEvent.ACTION_DOWN),滑动(MotionEvent.ACTION_MOVE),抬起手(MotionEvent.ACTION_UP)。重写onTouchEvent()方法,其参数就是MotionEvent,只要是重写触摸相关的方法,参数一般都含有MotionEvent,可见其重要性。

而所谓的事件拦截机制,其实就是对MotionEvent事件的拦截和分发过程,即当一个MotionEvent产生了以后,系统需要把这个事件传递给具体的View,而这个过程就是事件的拦截和分发过程。要完成这个过程需要三个很重要的方法来共同完成:dispatchTouchEvent、onInterceptTouchEvent和onTouchEvent,先来介绍下这几个方法吧!

    public boolean dispatchTouchEvent(MotionEvent ev)

用来进行事件的分发。如果事件能够传递给当前View,那么此方法一定会被调用,返回结果受当前View的onTouchEvent和下级View的dispatchTouchEvent方法的影响,表示是否消耗当前事件。

    public boolean onInterceptTouchEvent(MotionEvent event)

在上述方法内部调用,用来判断是否拦截某个事件,如果当前View拦截某个事件,那么在同一个事件序列当中,此方法不会被再次调用,返回结果表示是否拦截当前事件。

    public boolean onTouchEvent(MotionEvent event)

在dispatchTouchEvent方法中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一个事件序列中,当前View无法再次接收到事件。

它们的关系?请看以下的伪代码:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        boolean consume = false;
        if(onInterceptTouchEvent(ev)) {
            consume = onTouchEvent(ev);
        } else {
            consume = child.dispatchTouchEvent(ev);
        }
        return consume;
    }

通过以上伪代码我们可以知道点击事件的传递规则:
对于一个根ViewGroup来说,点击事件产生后,首先会传递给它,这时它的dispatchTouchEvent就会被调用,如果这个ViewGroup的onInterceptTouchEvent方法返回true就表示它要拦截当前事件,接着事件就会交给这个ViewGroup处理,即它的onTouchEvent方法就会被调用;如果这个ViewGroup的onInterceptTouchEvent方法返回false就表示它不拦截当前事件,这时当前事件就会继续传递给它的子元素,接着子元素的dispatchTouchEvent方法就会被调用,如此反复知道事件被最终处理。

在以上理论的基础上进行进一步的实践,其实实践过程非常简单,就是重写了事件拦截和处理的几个方法,并通过log的方式观察几个方法的执行过程。

完成实践需要两个ViewGroup和一个View,分别给它们命名,最外层的ViewGroup为MyViewGroupA,中间ViewGroup为MyViewGroupB,最底层的View为MyView。本例的整个布局如图所示:

结构布局

对于ViewGroup来说,重写了如下所示的三个方法:

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupA_dispatchTouchEvent: " + ev.getAction());
        boolean result = super.dispatchTouchEvent(ev);
        Log.i(TAG, "MyViewGroupA_dispatchTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupA_onInterceptTouchEvent: " + ev.getAction());
        boolean result = super.onInterceptTouchEvent(ev);
        Log.i(TAG, "MyViewGroupA_onInterceptTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyViewGroupA_onTouchEvent: " + event.getAction());
        boolean result = super.onTouchEvent(event);
        Log.i(TAG, "MyViewGroupA_onTouchEvent_after: " + result);
        return result;
    }

而对于View来说,重写了如下所示的两个方法:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyView_onTouchEvent: " + event.getAction());
        boolean result = super.onTouchEvent(event);
        Log.i(TAG, "MyView_onTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyView_dispatchTouchEvent: " + event.getAction());
        boolean result = super.dispatchTouchEvent(event);
        Log.i(TAG, "MyView_dispatchTouchEvent_after: " + result);
        return result;
    }

首先不修改任何值,只是点击一下View,然后看Log会怎样记录我们的操作和程序的响应。

        10-08 02:32:46.216 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 0
        10-08 02:32:46.216 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 0
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 0
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent: 0
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent_after: false
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent: 0
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent: 0
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent_after: false
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent_after: false
        10-08 02:32:46.217 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent: 0
        10-08 02:32:46.218 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent_after: false
        10-08 02:32:46.218 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: false
        10-08 02:32:46.218 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onTouchEvent: 0
        10-08 02:32:46.218 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onTouchEvent_after: false
        10-08 02:32:46.218 8213-8213/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: false

可见,正常情况下,事件的传递顺序是:
MyViewGroupA ——> MyViewGroupB ——> View
传递时先执行dispatchTouchEvent()方法,再执行onInterceptTouchEvent()方法。

事件的处理顺序是:
View ——> MyViewGroupA ——> MyViewGroupB
处理时都是执行onTouchEvent()方法。

这个日志也证实了伪代码的准确性。

可以将上面的整个事件过程整理成如图:

事件过程

那么假设MyViewGroupB将事件拦截住了呢?会不会就是不执行MyView的相关事件方法呢?让我们试试给MyViewGroupB的onInterceptTouchEvent()方法返回true看看。

        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent_after: true
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent_after: false
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: false
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onTouchEvent: 0
        10-08 02:59:34.694 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onTouchEvent_after: false
        10-08 02:59:34.695 31295-31295/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: false

和设想一样,MyView没事可干了。那么如果MyView处理事件时直接返回true,会怎么样呢?

修改MyView的代码如下所示:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyView_onTouchEvent: " + event.getAction());
        super.onTouchEvent(event);
        Log.i(TAG, "MyView_onTouchEvent_after: " + true);
        return true;
    }

再来看看Log,如下所示:

        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 0
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 0
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 0
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent: 0
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent_after: false
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent: 0
        10-08 05:53:24.361 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent: 0
        10-08 05:53:24.362 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent_after: true
        10-08 05:53:24.362 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent_after: true
        10-08 05:53:24.362 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: true
        10-08 05:53:24.362 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: true
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent_after: false
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent: 1
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent_after: true
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent_after: true
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: true
        10-08 05:53:24.442 2634-2634/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: true

这里会发现处理的过程好像变的更长了,其实这里给MyView的点击事件返回true就表示消耗了事件,就如上面介绍onTouchEvent方法时所描述的,消耗了就开始接收下次的事件。相信读者已经注意到了Log日志中getAction()返回的数值,那么这些数值代表着什么呢?

其实0表示ACTION_DOWN事件,1表示ACTION_UP事件,2表示ACTION_MOVE事件。
结合这些要点,在看面的Log日志,发现在执行ACTION_DOWN事件时,MyView的onTouchEvent方法返回true后,两个ViewGroup都不执行onTouchEvent方法,这也就是说MyView直接结束了这次事件,不再传回两个ViewGroup。但是,在结束了ACTION_DOWN事件后,紧接着开始执行了ACTION_UP事件,说明只有当MyView的onTouchEvent返回true才会执行下面的事件。

那么,恢复原代码后修改MyViewGroupB内的onTouchEvent返回值为true:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyViewGroupB_onTouchEvent: " + event.getAction());
        super.onTouchEvent(event);
        Log.i(TAG, "MyViewGroupB_onTouchEvent_after: " + true);
        return true;
    }

现在再来观察Log日志文件:

        10-08 06:31:49.333 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 0
        10-08 06:31:49.333 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onInterceptTouchEvent_after: false
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_onTouchEvent_after: false
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyView_dispatchTouchEvent_after: false
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent: 0
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent_after: true
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: true
        10-08 06:31:49.334 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: true
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent: 1
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent: 1
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_onInterceptTouchEvent_after: false
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent: 1
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent: 1
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_onTouchEvent_after: true
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupB_dispatchTouchEvent_after: true
        10-08 06:31:49.421 9604-9604/com.example.eventinterceptionmechanism I/TestViewAndViewGroup: MyViewGroupA_dispatchTouchEvent_after: true

我们会发现结果和修改MyView的onTouchEvent方法的结果是一样的,也是返回true后直接结束事件,但是在第二次处理事件的时候,MyView就没再参与事件的处理,也就是说一旦onTouchEvent返回值为false就会导致在本次处理过程中后面的事件将不再分发给该View。

通过上面的分析,相信对事件的拦截,分发和处理有了一定的了解。

代码

那么最后再贴上测试的源代码:

MyViewGroupA.java
package com.example.eventinterceptionmechanism;

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

/**
 * MyViewGroupA
 * Created by shize on 2016/10/7.
 */
public class MyViewGroupA extends LinearLayout {

    private final static String TAG = "TestViewAndViewGroup";

    public MyViewGroupA(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupA_dispatchTouchEvent: " + ev.getAction());
        boolean result = super.dispatchTouchEvent(ev);
        Log.i(TAG, "MyViewGroupA_dispatchTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupA_onInterceptTouchEvent: " + ev.getAction());
        boolean result = super.onInterceptTouchEvent(ev);
        Log.i(TAG, "MyViewGroupA_onInterceptTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyViewGroupA_onTouchEvent: " + event.getAction());
        boolean result = super.onTouchEvent(event);
        Log.i(TAG, "MyViewGroupA_onTouchEvent_after: " + result);
        return result;
    }
}
MyViewGroupB.java
package com.example.eventinterceptionmechanism;

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

/**
 * MyViewGroupB
 * Created by shize on 2016/10/7.
 */
public class MyViewGroupB extends LinearLayout {

    private final static String TAG = "TestViewAndViewGroup";

    public MyViewGroupB(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupB_dispatchTouchEvent: " + ev.getAction());
        boolean result = super.dispatchTouchEvent(ev);
        Log.i(TAG, "MyViewGroupB_dispatchTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "MyViewGroupB_onInterceptTouchEvent: " + ev.getAction());
        boolean result = super.onInterceptTouchEvent(ev);
        Log.i(TAG, "MyViewGroupB_onInterceptTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyViewGroupB_onTouchEvent: " + event.getAction());
        boolean result = super.onTouchEvent(event);
        Log.i(TAG, "MyViewGroupB_onTouchEvent_after: " + result);
        return result;
    }
}
MyView.java
package com.example.eventinterceptionmechanism;

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

/**
 * MyView
 * Created by shize on 2016/10/7.
 */
public class MyView extends TextView {

    private final static String TAG = "TestViewAndViewGroup";

    public MyView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyView_onTouchEvent: " + event.getAction());
        boolean result = super.onTouchEvent(event);
        Log.i(TAG, "MyView_onTouchEvent_after: " + result);
        return result;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "MyView_dispatchTouchEvent: " + event.getAction());
        boolean result = super.dispatchTouchEvent(event);
        Log.i(TAG, "MyView_dispatchTouchEvent_after: " + result);
        return result;
    }
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<com.example.eventinterceptionmechanism.MyViewGroupA 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:orientation="vertical"
    android:gravity="center_horizontal"
    tools:context="com.example.eventinterceptionmechanism.MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:textSize="24sp"
        android:textAlignment="center"
        android:text="@string/view_group_a"
        android:textColor="@color/back"/>

    <com.example.eventinterceptionmechanism.MyViewGroupB
        android:layout_width="380dp"
        android:layout_height="450dp"
        android:orientation="vertical"
        android:background="@color/back"
        android:gravity="center_horizontal">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="120dp"
            android:textSize="24sp"
            android:textAlignment="center"
            android:text="@string/view_group_b"
            android:textColor="@color/write"/>

        <com.example.eventinterceptionmechanism.MyView
            android:layout_width="300dp"
            android:layout_height="200dp"
            android:textSize="24sp"
            android:textAlignment="center"
            android:text="@string/my_view"
            android:background="@color/blue"
            android:textColor="@color/write"/>

    </com.example.eventinterceptionmechanism.MyViewGroupB>

</com.example.eventinterceptionmechanism.MyViewGroupA>

感谢阅读,学习重在坚持,贵在坚持,那么下次再见。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值