Android的事件分发

来源:互联网 发布:4个月培训java出来也废 编辑:程序博客网 时间:2024/05/22 14:23

       首先在写这篇博客的时候,我们先举个例子。在一个安卓的布局文件中,我们加一个textview。那么问题来啦,当TouchEvent发生时,是谁先接收这个事件呢,是Activity(虽然之前肯定是一系列的传感器,但与安卓相关时是Activity)然后我们解释一下事件分发的三个关键方法:

public boolean dispatchTouchEvent(MotionEvent ev)
        它是View或ViewGroup处理事件分发的发起者,Activity接收到这个触控事件最先调起的就是这个方法,然后在判断是拦截还是分发事件给子容器。

public boolean onInterceptTouchEvent(MotionEvent ev)
       ViewGroup专用,用来拦截事件,是处理事件冲突的最佳地点

public boolean onTouchEvent(MotionEvent event)
       触控事件的真正处理者,最后每个事件都会在这里被处理

       首先我们需要知道,触摸到任何一个控件 ,都会调用该控件的dispatchTouchEvent().具体的传递顺序可以看一下下面的伪代码。

public boolean dispatchTouchEvent(MotionEvent ev){ boolean isConsumed = false;   if(onInterceptTouchEvent(ev)){     isCousumed = this.onTouchEvent(ev);   }else{      isConsumed = childView.dispatchTouchEvent(ev);   }   return isConsumed;}

再举个粟子

这里写图片描述

       activity就好比我们的老板,viewgroup好比总经理 ,TextView好比员工。它们默认都是无法完成任务的。当老板布置一个任务分发下来的时候,总经理先执行它的拦截事件,并安排给员工做,那么就调用TextView的dispatchtouchEvent(),如果这件事情,员工能做(也就是开发者需要它完成),那么执行员工的ontouchEvent(),返回true。如果不能做,返回给viewgroup,这个时候,就需要总经理自己做,如果总经理能做,那么执行总经理 的ontouchEvent(),返回true。如果不能做,返回给activity。最后,如果开发者需要它拦截,就改为true,否则即为默认的false.

       一句话就能概括,ViewGroup收到事件后调用dispatch,在dispatch中先检查是否要拦截,若拦截则ViewGroup吃掉事件,否则交给有处理能力的子容器处理。

另外补充一点:
       从用户点击屏幕开始触发一个系列的点击事件时,事件真正的传递流程是:Activity(PhoneWindow)->DecorView->ViewGroup->View,在到达ViewGroup之前还有一个DecorView,事件是从Activity传过来的,但这些东西其实和ViewGroup的原理是一样的,Activity能看做一个大的ViewGroup,当它的DecorView包含的所有子View没有人能够消耗事件的时候(这样说并不严谨)最后还是会交给Activity处理。

再补充一点:
       任何View只要拒绝了一系列事件中的ACTION_DOWN(返回false),则后续事件都不会再传递过来了。但如果拒绝了其他的事件,后续事件还是可以传过来的,比如View某次ACTION_MOVE没处理,这个没处理的事件最后会被Activity消耗掉(而不是View的父容器),但后续的事件还是会继续传给该View。

       初出茅庐,请批评指教。并在此感谢指导我的老大!

0 0