Android事件分发机制

本篇仅作为自学笔记,以及学习分享,内容来源于:

https://blog.youkuaiyun.com/qq_30379689/article/details/53967177#commentBox

关于Android事件分发机制,面试回答总结就是以下几点:

  • dispatchTouchEvent 
    • return true:表示该View内部消化掉了所有事件
    • return false:表示事件在本层不再继续进行分发,并交由上层控件的onTouchEvent方法进行消费
    • return super.dispatchTouchEvent(ev):默认事件将分发给本层的事件拦截onInterceptTouchEvent方法进行处理
  • onInterceptTouchEvent 
    • return true:表示将事件进行拦截,并将拦截到的事件交由本层控件的onTouchEvent进行处理
    • return false:表示不对事件进行拦截,事件得以成功分发到子View
    • return super.onInterceptTouchEvent(ev):默认表示不拦截该事件,并将事件传递给下一层View的dispatchTouchEvent
  • onTouchEvent 
    • return true:表示onTouchEvent处理完事件后消费了此次事件
    • return fasle:表示不响应事件,那么该事件将会不断向上层View的onTouchEvent方法传递,直到某个View的onTouchEvent方法返回true
    • return super.dispatchTouchEvent(ev):表示不响应事件,结果与return false一样

自定义MyView 

/**
 * Created by zzf on 2018/8/29.
 */

public class MyView extends View {
    public MyView(Context context) {
        super(context);
    }

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

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        LogUtils.d("MyView------->onTouchEvent");

        return super.onTouchEvent(event);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        LogUtils.d("MyView------->dispatchTouchEvent");
        return super.dispatchTouchEvent(event);
    }
}

自定义MyViewGroup01 

/**
 * Created by zzf on 2018/8/29.
 */

public class MyViewGroup01 extends LinearLayout {
    public MyViewGroup01(Context context) {
        super(context);
    }

    public MyViewGroup01(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroup01(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        LogUtils.d("MyViewGroup01------->dispatchTouchEvent");

        return super.dispatchTouchEvent(ev);
//        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        LogUtils.d("MyViewGroup01------->onInterceptTouchEvent");

        return super.onInterceptTouchEvent(ev);
//        return false;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        LogUtils.d("MyViewGroup01------->onTouchEvent");

//        return super.onTouchEvent(event);
        return false;
    }
}

 自定义MyViewGroup02

/**
 * Created by zzf on 2018/8/29.
 */

public class MyViewGroup02 extends LinearLayout {
    public MyViewGroup02(Context context) {
        super(context);
    }

    public MyViewGroup02(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroup02(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        LogUtils.d("MyViewGroup02------->dispatchTouchEvent");

        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        LogUtils.d("MyViewGroup02------->onInterceptTouchEvent");

        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        LogUtils.d("MyViewGroup02------->onTouchEvent");

        return super.onTouchEvent(event);
    }
}

xml布局文件 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <com.haiyungroup.oceansonic.customview.MyViewGroup02
        android:background="#ff0000"
        android:layout_width="300dp"
        android:layout_height="500dp">

        <com.haiyungroup.oceansonic.customview.MyViewGroup01
            android:background="#00ff00"
            android:layout_width="200dp"
            android:layout_height="400dp">

            <com.haiyungroup.oceansonic.customview.MyView
                android:background="#0000ff"
                android:layout_width="@dimen/dimen_150dp"
                android:layout_height="300dp" />
        </com.haiyungroup.oceansonic.customview.MyViewGroup01>
    </com.haiyungroup.oceansonic.customview.MyViewGroup02>


</FrameLayout>

分析事件传递

点击MyView(即蓝色部分):先接收事件的是父容器(MyViewGroup02)往下分发,而事件的分发过程中分为两步骤

  • 分发过程
  • 处理过程

其正常的分发事件结果为

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
MyViewGroup01 onInterceptTouchEvent
MyView dispatchTouchEvent
//处理过程
MyView onTouchEvent
MyViewGroup01 onTouchEvent
MyViewGroup02 onTouchEvent

1、dispatchTouchEvent(分发事件)

如果在MyViewGroup01的dispatchTouchEvent方法中返回true,表示需要在MyViewGroup01消费了整个事件,即不会再分发,也不会再处理。dispatchTouchEvent方法中返回true的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent

如果在MyViewGroup01的dispatchTouchEvent方法中返回false,表示在MyViewGroup01点击事件在本层不再继续进行分发,并交由上层控件的onTouchEvent方法进行消费。dispatchTouchEvent方法中返回false的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
//处理过程
MyViewGroup02 onTouchEvent

2、onInterceptTouchEvent(拦截事件)

如果在MyViewGroup01的onInterceptTouchEvent方法中返回true,表示需要在MyViewGroup01拦截这个点击事件,不再继续往下分发,即MyView不再执行dispatchTouchEvent方法。但是只是分发结束了而已,接着开始处理事件。下面是onInterceptTouchEvent方法中返回true的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
MyViewGroup01 onInterceptTouchEvent
//处理过程
MyViewGroup01 onTouchEvent
MyViewGroup02 onTouchEvent

如果在MyViewGroup01的onInterceptTouchEvent方法中返回false,表示需要在MyViewGroup01不会拦截这个点击事件,继续往下分发。下面是onInterceptTouchEvent方法中返回false的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
MyViewGroup01 onInterceptTouchEvent
MyView dispatchTouchEvent
//处理过程
MyView onTouchEvent
MyViewGroup01 onTouchEvent
MyViewGroup02 onTouchEvent

3、onTouchEvent(消费事件)

如果MyViewGroup01的onTouchEvent方法中返回true,表示MyViewGroup01可以将该事件直接消费掉了,即分发结束后,处理事件的时候,直接处理到MyViewGroup01就可以结束了。下面是onTouchEvent方法中返回true的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
MyViewGroup01 onInterceptTouchEvent
MyView dispatchTouchEvent
//处理过程
MyView onTouchEvent
MyViewGroup01 onTouchEvent

如果MyViewGroup01的onTouchEvent方法中返回false,表示MyViewGroup01不可以将该事件直接消费掉,即事件继续往上处理。下面是onTouchEvent方法中返回false的打印信息

//分发过程
MyViewGroup02 dispatchTouchEvent
MyViewGroup02 onInterceptTouchEvent
MyViewGroup01 dispatchTouchEvent
MyViewGroup01 onInterceptTouchEvent
MyView dispatchTouchEvent
//处理过程
MyView onTouchEvent
MyViewGroup01 onTouchEvent
MyViewGroup02 onTouchEvent
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值