Android事件分发机制最浅解析

**

android事件分发机制解析

**

年幼时候的我看了很多关于时间分发的文章,不管是深入解析,还是浅淡,都让我有种茫茫然的感觉;完了在此疫情待业的情况下,我自己实践并废了老鼻子劲的浅入代码分析,终于好像明白了一点,为了不辜负自己一下午的边玩边看,我在此记录一下。如果能给各位老师带来一点帮助就很好了,如果有不对的地方,那也请及时给我指出来,不要让我继续迷糊,谢谢。

事件分发涉及的三个函数

//该函数负责事件分发,拦截函数和事件处理函数都在此方法体中被调用
public boolean dispatchTouchEvent(MotionEvent ev)

//该函数负责事件拦截
public boolean onInterceptTouchEvent(MotionEvent ev)

//该函数负责事件处理
public boolean onTouchEvent(MotionEvent ev)

注意事项:

1、事件的分发是从上到下,即从外层的group向内层的view传递;
(activity->decorView->group->…->view)
2、事件的处理是从内向外分发,即最底层view先处理,没有进行处理再往上层viewgroup乃至activity分发;但是有个前提,就是事件处理过程中没有处理且向上分发的view中的ontouch()和onTouchEvent()中的返回一定是false(必须设置ontouchlistener或者复写ontouchevent且设置返回值为false),并且没有设置onclick事件(onclick函数会消耗事件传递);通俗的解释应该是明确这个事件我不响应,才会向上分发

分析开始

代码
	我这边先贴一下自己的写的伪代码,希望能给分析带来一点帮助
         //拦截函数
    private boolean onIntercept() {
        boolean isIntercept ;
        ...
        ...
        return isIntercept;

    }
    
	//事件分发函数
    private boolean dispatchEvent() {
        boolean isPatch ;
        
        //如果当前进行拦截拦截,调用dispatchTransformedTouchEvent,但是将参数设置为null
        if (onIntercept()) {
            dispatchTransformedTouchEvent(null);
        }
        //不拦截,调用dispatchTransformedTouchEvent,将参数设置为继续分发的子view
        else {
            dispatchTransformedTouchEvent(child);
        }


        return isPatch;
    }
   
		//该函数中包含事件处理函数
    private boolean dispatchTransformedTouchEvent(Child child) {
        //当传递进来的child为空,就调用父类,即父view的dispatchTouchEvent
        if (child == null) {
            super.dispatchTouchEvent(event);
        } else {
            //调用参数child的dispatchTouchEvent
            child.dispatchTouchEvent(event);
        }
    }

    private void dispatchTouchEvent(){
        //如果当前设置过ontouchlistener,就执行下面方法并返回
        if (li != null && li.mOnTouchListener != null
                && (mViewFlags & ENABLED_MASK) == ENABLED
                && li.mOnTouchListener.onTouch(this, event)) {
				//onclick方法在onTouchEvent中,当ontouch返回true的时候,代表事件被消费了(看下段代码的条件判断),所以不会往下走onTouchEvent方法,所以就不执行onclick了
            result = true;
        }
        //如果没有设置onTouchListener,就调用重载的onTouchEvent方法,注意,onclick方法在onTouchEvent(event)的action_up中被执行
        if (!result && onTouchEvent(event)) {
            result = true;
        }
    }
流程解析(史上最浅解析)
  1. activity接收到触摸事件;

  2. 事件通过activity上传给最顶层view:DecorView,该view就是一个ViewGroup,事件由此开始传递;

  3. 当前view/viewgroup调用dispatchTouchEvent()后,会在方法体内先判断是否被拦截,即onIntercept()的返回是否为ture,

    • 为true则表示被拦截,则调用父view的dispatchTouchEvent()方法,如果设置了ontoulistener,使用setOnTouchListener(new OnTouchListener())中的OnTouchListener中的ontouch()事件进行处理,否则调用复写的onTouchEvent()方法进行处理,否则不处理,玩完;
    • 为false则表示未被拦截,则调用子view的dispatchTouchEvent()方法,子view进行onIntercept()方法判断是否拦截,然后该步骤循环往复
    • 如果该事件被拦截或者走到最后一个子view;该子view设置了ontoulistener或者复写的onTouchEvent()方法并且返回值为true,则事件被消耗掉,事件分发结束;
    • 如果拦截该事件的view设置了OnTouchListener或者复写了onTouchEvent(),当返回值为false且没有设置onclick事件的情况下,事件的处理会向上分发,即还会上传给上层的viewgroup等,直至遇到一个返回值为true的消耗掉该事件,事件分发结束。
    • 如果拦截该事件的view没有设置了OnTouchListener且没有复写了onTouchEvent(),事件不处理也不会被传递,事件分发结束。

不管是action是down还是move还是up,都是走的上述流程,cancle我没看,后面心情好了再说吧。

这应该就是责任链模式,只要事件不被消耗掉,随便你怎么处理,每一层都可以处理和响应。(欢迎纠正)

再一次的这就完了,自己重新又扒拉了一遍源码且打印日志查看后重新组织了一遍文章;治学不怕更严谨,希望之前写错的地方误人子弟不要误的太深,实在不好意思。

错别字害死人,再改一版,,,

谢谢大哥大嫂们。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值