android事件分发机制

今天看了一篇文章关于android事件分发机制的,以前对安卓的事件分发机制一直处于模糊状态,今天看了文章后加上自己写了一点点有了点灵感,所以记下来方便以后在开发的过程中温故而知新。

先介绍View的事件:

android中的基础控件是view,其他的组件无非是继承自view,先把事件分发机制最重要的一句话写在前面,就是所有的组件只要被点击就会出发其中的dispatchTouchEvent方法,但是这个方法并不是每个组件都有的方法,例如像button里没有这个方法,再进入button的父类textview中去找,但是也找不到这个方法,到这里大家不要担心,我们再进入这个textview的父类view中,在这里我们就找到了,方法的源码是这样的:

  1. public boolean dispatchTouchEvent(MotionEvent event) {  
  2.     if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&  
  3.             mOnTouchListener.onTouch(this, event)) {  
  4.         return true;  
  5.     }  
  6.     return onTouchEvent(event);  
  7. }  
这里有个if语句主要的作用就是让不同的返回值进入不同的方法,例如if中的返回值是true则进入onTouch方法的逻辑中,如果返回的是false则进入的是下面的ontTouchEvent方法中(button的onclicklistener事件就在这个方法中),下面我们再来介绍一下if中的三个参数,只有同时返回为true的时候才能进入到ontouch方法中,第一个参数mOnTouchListener 表示的是我们如果给一个组件设置了onToucherListener事件后则这个参数就不为null(例如:button.setOnTouchListener(....)), 第二个参数表示的是这个组件必须有能点击的属性,第三个参数是最重要的,这个参数就是在你组件设置onToucherListener后里面你给的返回值:

  1. button.setOnTouchListener(new OnTouchListener() {  
  2.     @Override  
  3.     public boolean onTouch(View v, MotionEvent event) {  
  4.         Log.d("TAG""onTouch execute, action " + event.getAction());  
  5.         return false;  
  6.     }  
  7. }); 
就是里面那个false,默认的是返回false,当然你也可以设置为true,这样的话就进入到了onTouch方法中,否则就进入到onTouchEvent中,如果你给一个button同时设置了onclicklistener事件和ontouchlistener事件,别在犹豫先执行哪个,系统会自动第一个执行ontouchlistener事件然后再调用里面的dispatchTouchEvent,根据你的ontouchlistener返回的是false或者是true分别进入到ontouch方法或者ontouchevent方法中,如果是进入到ontouchevent方法中则继续执行这个方法中的onclicklistener事件,所以同时设置这两个事件先后顺序是先ontouchlistener然后再onclicklistener,因为onclicklistener在ontouchlistener中的ontouchevent方法中,我自己都差点被绕晕了。

viewGroup事件的分发:

大家都知道viewGroup就是一个包含了多个view的一个容器也可以说是一个布局,但是都继承自view所以viewGroup里面也有dispatchTouchEvent方法,这个方法也是用来执行像view那样的单个组件的事件操作,但是这个不同的是你点击事件先传给view,view再传给viewGroup先执行onInterceptTouchEvent方法,

  1.  @Override  
  2.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  3.         return true;  
  4.     }
这个方法返回的如果为true执行进入源码进行一个非的操作变成了false表示不进行事件分发,则屏蔽了viewgroup中的所有子view的事件分发,如果返回的是一个false则进入源码进行一个非的操作后变成了true表示向下进行事件的分发,如果是这样则执行viewGroup中的dispatchTouchEvent,在这个方法中先遍历一次这个viewGroup里面的所有子view,判断哪个子view被点击了就执行上面所讲到的view的事件分发操作,如果子view没有消费这个事件,则会将这个事件返回给viewGroup的dispatchTouchEvent来执行。

总之:当你点击了某个控件,首先会去调用该控件所在布局的dispatchTouchEvent方法,然后在布局的dispatchTouchEvent方法中找到被点击的相应控件,再去调用该控件的dispatchTouchEvent方法。假如MyLayout继承自LinearLayout如果我们点击了MyLayout中的按钮,会先去调用MyLayout的dispatchTouchEvent方法,可是你会发现MyLayout中并没有这个方法。那就再到它的父类LinearLayout中找一找,发现也没有这个方法。那只好继续再找LinearLayout的父类ViewGroup,你终于在ViewGroup中看到了这个方法,按钮的dispatchTouchEvent方法就是在这里调用的。

基本思路就是这样,如果我将不详细可以参看一下这篇文章http://sc.qq.com/fx/u?r=SORKRmA

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值