Android 事件分发 笔记

参考文jsyjst:https://juejin.im/post/5e3e5d50e51d4527255c97e8

概:

  • 当一个点击事件发生后,总是先传递给当前的Activity,由Activity的dispatchTouchEvent进行分发,而Activity会将事件传递给Window,然后由Window的唯一实现类PhoneWindow将事件传递给DecorView,接着DecorView将事件传递给自己的父类ViewGroup,此时的ViewGroup就是通过setContentView所设置的View,故可以称为顶级View,这时候ViewGroup可能是自己处理该事件或者传递给子View,但是最终都会调用View的dispatchTouchEvent来处理事件。
  • 在View的dispatchTouchEvent中,如果设置了onTouchListener,会调用其onTouch方法,如果onTouch返回true,则不再调用onTouchEvent。如果有设置点击事件,则在onTouchEvent会调用onClick方法。如果子View的onTouchEvent返回了false,则表示不消耗事件,事件会回传给上一级的ViewGroup的onTouchEvent,如果所有的ViewGroup都没有返回true,则最终会回传到Activity的onTouchEvent。

事件类型

  • MotionEvent.ACTION_DOWN手指刚接触屏幕,一般为事件的开始
  • MotionEvent.ACTION_MOVE手指在屏幕移动,在移动的过程中会产生多个move事件
  • MotionEvent.ACTION_UP手指从屏幕上松开的一瞬间
  • MotionEvent.ACTION_CANCEL结束事件,非人为原因

本质

其实就是将点击事件(MotionEvent)传递到某个具体的View处理的整个过程。

顺序

事件传递的顺序:Activity->Window->DecorView->ViewGroup->View。

方法

一般处理情况有 事件分发->事件拦截->事件处理

1.事件分发:boolean dispatchTouchEvent(MotionEvent ev) {}

    所返回的结果受当前View的onTouchEvent和下级的dispatchTouchEvent的影响,表示是否消耗当前事件。

  • true 当前view消耗
  • false 停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,则事件将被系统消费,处理

2.事件拦截:boolean onInterceptTouchEvent(MotionEvent ev){}

    ViewGroup才有此方法,默认不拦截super.onInterceptTouchEvent(ev)

  • true 拦截事件 交给onTouchEvent
  • false 不拦截 分发下层 子View dispatchTouchEvent进行处理

3.事件处理 onTouchEvent(MotionEvent ev){}

       在dispatchTouchEvent中调用,用来处理点击事件,返回结果表示是否消耗当前事件,如果不消耗,则在同一事件序列中,当前View无法再接受到剩下的事件,并且事件将重新交给它的父元素处理,即父元素的onTouchEvent会被调用

  • true:表示onTouchEvent处理后消耗了当前事件
  • false:不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费,如果到最顶层View还是返回false,则该事件不消费,将交由Activity的onTouchEvent处理。
  • super.onTouchEvent(ev):默认消耗当前事件,与返回true一致。

===========================================================================================

分发机制

1. Activity事件的分发机制

Activity->Window->DecorView

当一个点击事件发生时,事件总是最先传递到当前Activity中,由Activity的dispatchTouchEvent来进行事件分发。而Activity会将事件传递给Window对象来分发,Window对象再传递给DecorView。

public boolean dispatchTouchEvent(MotionEvent ev) {
    	//点击事件的开始一般为按下事件,所以总是true
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();//back home等处理
			
        }
		//如果Activity所属Window的dispatchTouchEvent返回了ture
		//则Activity.dispatchTouchEvent返回ture,点击事件停止往下传递
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
		//如果Window的dispatchTouchEvent返回了false,则点击事件传递给Activity.onTouchEvent
        return onTouchEvent(ev);
    }

其实DecorView就是我们通过setContentView设置布局的父容器

流程大致:

Activity(dispatchTouchEvent)->

Window(getwindow.superDispatchTouchEvent)->

DecorView(superDispatchTouchEvent)->

ViewGroup(dispatchTouchEvent)-> true:Activity.dispatchTouchEvent=true/false:Activity.dispatchTouchEvent=Activity.onTouchEvent()返回值

2. ViewGroup事件的分发机制

不拦截事件时,首先会遍历ViewGroup的所有子元素,然后判断子元素是否能够接受到点击事件。判断的依据是:子元素是否在播放动画和点击事件的坐标是否落在子元素的区域内。如果找到一个目标子View来处理事件时,则调用dispatchTransformedTouchEvent()方法。

3. View事件的分发机制

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值