android事件机制

首先说明一个概念:正常情况下android中的事件,是必须要先经过传递流程然后再经过处理流程的,要记住这个先后顺序

在ViewGroup中,有下面3个方法:
  1. dispatchTouchEvent 该方法用来分发事件,一般不会重写这个方法
  2. onInterceptTouchEvent 该方法用来拦截事件
  3. onTouchEvent 该方法用来处理事件
在View中,只有2个方法:
  1. dispatchTouchEvent 该方法用来分发事件,一般不会重写这个方法
  2. onTouchEvent 该方法用来处理事件
事件列
  1. android事件是一些列的时间,从手机按下的down时间开始 经过一些列的move事件,最后是up事件
  2. 如果ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return false,那么后续的move,up等事件将继续会传递给该ViewGroup,之后才和down事件一样传递给目标view的onTouchEvent()来处理
  3. 如果ViewGroup的onInterceptTouchEvent()在接收到down事件处理完成之后return true,那么后续的move,up等事件将不再传递给该ViewGroup的onInterceptTouchEvent(),注意:目标view接收不到任何事件

下面用一个小demo来验证这些方法

这里我们使用两个自定义的ViewGroup和一个自定义的View来演示

public class ViewGroupA extends LinearLayout {

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

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("小付", "ViewGroupB  dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("小付", "ViewGroupB  onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
//        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("小付", "ViewGroupB  onTouchEvent");
        return super.onTouchEvent(event);
//        return true;
    }
}

public class ViewGroupB extends LinearLayout {

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

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

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

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("小付", "ViewGroupB  dispatchTouchEvent");
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.e("小付", "ViewGroupB  onInterceptTouchEvent");
        return super.onInterceptTouchEvent(ev);
//        return true;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("小付", "ViewGroupB  onTouchEvent");
        return super.onTouchEvent(event);
//        return true;
    }
}

public class MyView extends View {
    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 dispatchTouchEvent(MotionEvent event) {
        Log.e("小付", "MyView  dispatchTouchEvent");
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.e("小付", "MyView  onTouchEvent");
//        return super.onTouchEvent(event);
        return true;
    }
}

最后,把他们嵌套在一起,activity的布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

   <com.parade.myapplication.ViewGroupA
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:gravity="center"
       android:background="#ff0033">
       
       <com.parade.myapplication.ViewGroupB
           android:layout_width="@dimen/dp_200"
           android:layout_height="@dimen/dp_200"
           android:gravity="center"
           android:background="#336699">

           <com.parade.myapplication.MyView
               android:id="@+id/my_view"
               android:layout_width="@dimen/dp_100"
               android:layout_height="@dimen/dp_100"
               android:background="#ffff33"/>

       </com.parade.myapplication.ViewGroupB>
       
   </com.parade.myapplication.ViewGroupA>

</LinearLayout>

布局截图如下:

在这里插入图片描述

从里到外依次是ViewGroupA,ViewGroupB和MyView,现在点击最里层的MyView,打印结果如下
在这里插入图片描述

默认在事件的传递和处理流程中,没有任何拦截

下面我们做实验,让MyView在事件处理过程中拦截事件,及其onTouch事件返回true,打印结果如下

在这里插入图片描述
可见ViewGroupA和ViewGroupB并没有处理事件,因为MyView已经拦截了事件处理

再来做一个实验,这次我们让ViewGroupB在事件传递过程中拦截,即其onInterceptTouchEvent 方法返回true,打印结果如下:

在这里插入图片描述

可见事件并没有传递到MyView,因为在ViewGroupB已经把事件传递拦截了

详细请参考原文

发布了62 篇原创文章 · 获赞 45 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/parade0393/article/details/98476310