Android中事件分发机制

     Android(触摸屏)中应用程序与用户交互用的就是touch事件来完成的,一个界面上的控件会有很多,那么
 一个touch事件是如何传递的呢?
  一、简介
	Android中的touch事件都是以down(按下)事件开始,up(抬起)事件结束的
        事件类型有:ACTION_DOWN(按下)、ACTION_UP(抬起)、ACTION_MOVE(移动)
	           ACTION_POINT_DOWN(多个手指按下)、ACTION_POINT_UP(多个手指抬起)
  二、事件分发
      Android中的View分为两个,一类是ViewGroup(含有子类View);一类是View(没有子类View),两类的
    事件分发机制有所不同
      1.View
	有两个控件TextView和Button,分别点击一次,并且打印响应的信息(onTouch默认返回为false)
	单击一次有两个事件响应:down和up分别执行一次,首先down事件执行如下
	
button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                System.out.println("button");
                return false;
            }
        });

        textView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                System.out.println("textView");
                return false;
            }
        });

	    分别点击一次后打印出来的效果如下
	
	为什么点击两个控件最后打印出信息的数量是不同的呢,那我们首先要从TextView和Button的不同
      入手,TextView默认是不可点击的,Button是可以点击的,然后带着这两点不同,看看系统的源码有
      一下重大的发现呢!!
	①button和textView都是View的子类,通过setOnTouchListener把OnTouchListener对象传到View
	  
public boolean dispatchTouchEvent(MotionEvent event) {
	        ....
			//mOnTouchListener不为空,并且当前控件可用,onTouch方法对应得返回值
	        if (mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED &&
	                mOnTouchListener.onTouch(this, event)) {
	            return true;
	        }
			//如果if对于逻辑不成立,调用onTouchEvent
			//onTouch先于onTouchEvent,并且觉得当前onTouchEvent是否调用
	        return onTouchEvent(event);
	    }

	②两个子View的onTouch返回值都为false,那么会执行本View的onTouchEvent(Event);
	③View的onTouchEvent()方法执行如下
	
public boolean onTouchEvent(MotionEvent event) {
	       	....
			//判断当前控件是否有点击事件,如果有则执行if中逻辑,如果没有则不执行返回false
	        if (((viewFlags & CLICKABLE) == CLICKABLE ||
	                (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
	            switch (event.getAction()) {
					//点击事件触发点
	                case MotionEvent.ACTION_UP:
	                   ...
                       performClick();
                       ...
	            }
				//此处返回true则说明onTouchEvent,说明dispatchTouchEvent返回true,则响应所有事件
	            return true;
	        }
			//此处返回false,等同于onTouchEvent,dispatchTouchEvent返回false,不响应所有事件
	        return false;
	    }

	  TextView不可点击,那么直接返回false,表示事件没有被消耗,那么down事件没有被消耗,up事
	  件也不会继续执行,所以textView只输出了一次结果
	  Button可以默认可被点击,那么会继续执行if语句中的内容,继而回响应up事件,所以会输出两次
	  结果
 	④如果给TextView设置一个点击事件的监听,那么也会输出两次结果,这是为什么呢?因为在监听
	  事件的源码中有如下的一段代码
		
public void setOnClickListener(OnClickListener l) {
			//如果当前控件没有点击事件,设置一个点击事件
	        if (!isClickable()) {
	            setClickable(true);
	        }
	        mOnClickListener = l;
	    }

	  就算TextView不可点击,系统也会给它设置为可点击的,那么他就可以和Button一样了
     2.ViewGroup
	ViewGroup中事件分发和View有点不同,因为ViewGroup有子View,这就会有事件的分发或者拦截了
	每个ViewGroup都有以下三个方法
		dispatchTouchEvent();	负责事件的分发
		onInterceptTouchEvent();负责事件的拦截
		onTouchEvent();		负责响应事件
	ViewGroup布局如下图
		
	 首先是down事件的分发
	  ViewGroup①在分发事件之前会调用自己的onInterceptTouchEvent()方法判断是否拦截,如果返
	回false(不拦截),那么分发给ViewGroup②的dispatchTouchEvent事件,它在分发之前也会判断自己
	是否要拦截,如果不拦截,那么传递给子View③,这时③不能再向下分发啦,需要判断onTouchEvent
	是否消耗该down事件,如果返回为True(不消耗),继续向上返回给②的onTouchEvent,依次类推
	在分发的过程中如果ViewGroup把事件拦截或者消耗掉了down事件,那么后续的move,up等事件会直
	接传递给它不会再走判断的流程
  三、小结
	以上是对Android事件的简单理解,其实我们在用手机的时候主要就是在touch手机屏幕,对touch的
     原理搞明白了,那么对于view是否该获得事件,以及viewGroup是否该拦截事件都会非常清楚




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值