Android事件传递机制

原创 2016年05月30日 23:06:44

1、跟touch事件相关的三个方法:

用来分派event

public boolean dispatchTouchEvent(MotionEvent ev);


用来拦截event

public boolean onInterceptTouchEvent(MotionEvent ev);


用来处理event

public boolean onTouchEvent(MotionEventev);





2、三个方法的用法:

diapatchTouchEvent():用来分派事件,其中调用了onInterceptTouchEvent()onToucEvent(),一般不重写该方法。


OnInterceptTouchEvent():用来拦截事件。ViewGroup类中的源码实现就是{returnfalse;},表示不拦截该事件,事件将向下传递(传递给其子View);若手动重写该方法,使其返回true则表示拦截事件,事件将终止向下传递,事件有当前ViewGroup类来处理,就是调用该类的onTouchEvent()方法。


OnTouchEvent():用来处理事件。返回true则表示该View能处理该事件,事件将终止向上传递(传递给其父View);返回false表示不能处理,则把事件传递给其父ViewonTouchEvent()方法处理。


下面根据自己写的一个Demo进行具体的分析:

下面是该demo的布局效果图:







其代码如下:

Activity的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    
    <com.example.scrolllayouttest.MainLinearLayout
        android:layout_width="400dp"
        android:layout_height="400dp"
        android:background="#ffcc00">
        
        <com.example.scrolllayouttest.SubLinearLayout
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:background="#00cc00">
            
        </com.example.scrolllayouttest.SubLinearLayout>
    </com.example.scrolllayouttest.MainLinearLayout>

</LinearLayout>

Activity中的监听代码:

@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", " ActivityOne onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "ActivityOne onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "ActivityOne onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	}

MainLinearLayout的监听代码:

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
//		return true;
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	//	return true;
	}

SubLinearLayout的监听代码:


@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "SubLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "SubLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	//	return true;
	}

情景一:

可以看到现在所有的事件的传递函数都是默认返回super.onInterceptTouchEvent(ev)或者返回super.onTouchEvent(event);就是表示都不拦截,不处理事件。

运行程序,查看打印的Log信息:


可以分析,按下的ACTION_DOWN事件先是传递到MainLinearLayoutonInterceptTouchEvent中判断是否进行拦截,不拦截则会传递子ViewSubLinearLayout中,在SubLinearLayout中的onInterceptTouchEvent判断是否拦截,不拦截。由于传递到了最后一个View了,所以先由最后一个ViewonTouchEvent进行判断,是否处理该事件,由于是SubLinearLayout返回super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于MainLinearLayoutonTouchEvent返回的是super.onTouchEvent(event),表示不处理,所以事件继续向上传递;由于没有子View消费该事件,所以事件最后传递到ActivityonTouchEvent中,由Activity进行处理该事件。

情景二:


MainLinearLayout中的监听代码改为:

@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		// TODO Auto-generated method stub
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onInterceptTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
	//	return super.onInterceptTouchEvent(ev);
		return true;
		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		// TODO Auto-generated method stub
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_DOWN");
			break;

		case MotionEvent.ACTION_MOVE:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_MOVE");
			break;
		case MotionEvent.ACTION_UP:
			Log.i("Grament0524", "MainLinearLayout onTouchEvent  ACTION_UP");
			break;
		default:
			break;
		}
    <span style="font-family:Droid Sans;">//</span>          return super.onTouchEvent(event);
		return true;
	}

表示MainLinearLayout拦截该事件(在onInterceptTouchEvent中返回true),并且处理该事件(在onTouchEvent中返回true)。



根据其Log,可以分析,事件先是传递到MainLinearLayoutonInterceptTouchEvent中判断是否需要拦截该事件,由于是返回true,所以MainLinearLayout拦截了事件,事件就交由MainLinearLayoutonTouchEvent进行事件的处理了;在MainLinearLayoutonTouchEvent中,由于是返回了true,表示能处理该事件,所以后面的ACTION_MOVE,ACTION_UP都交由MainLinearLayoutonTouchEvent来处理。






版权声明:本文为博主原创文章,未经博主允许不得转载。

android 事件机制图文详解-从源码角度分析彻底理解事件传递机制(上)

最近在看android开发艺术一书,因此对android 事件机制有更深层次的理解,在此记录一遍 探讨Android事件传递机制前,务必明确android的两大基础控件类型:View和ViewGr...
  • javazejian
  • javazejian
  • 2016年01月07日 23:50
  • 1403

Android Touch事件传递机制全面解析(从WMS到View树)

转眼间近一年没更新博客了,工作一忙起来,很难有时间来写博客了,由于现在也在从事Android开发相关的工作,因此以后的博文也会更多地专注于这一块。 这篇文章准备从源码层面为大家带来Touch事件的传...
  • mmc_maodun
  • mmc_maodun
  • 2015年12月21日 07:43
  • 8371

Android事件分发传递回传机制详解

如果想参与实际开发项目,若不理解事件分发回传机制的话,几乎等于“”摸黑抓鳅”,因为几乎每个项目都会出现滑动冲突问题;而要想解决滑动冲突问题,必须先了解甚至掌握事件分发传递机制。等到了解决滑动冲突时,至...
  • qq_32059827
  • qq_32059827
  • 2016年09月18日 22:54
  • 1405

Android事件传递流程-伪代码

android 事件传递伪代码
  • u012227177
  • u012227177
  • 2017年04月24日 19:36
  • 350

Android触摸屏事件派发机制详解与源码分析一(View篇)

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN。因为CSDN也支持MarkDown语法了,牛逼啊!【工匠若水 http://blog.csdn.net/yanbobe...
  • yanbober
  • yanbober
  • 2015年05月21日 17:03
  • 51052

Android自定义view之事件传递机制

Android自定义view之事件传递机制 本文是自定义view入门的第二篇文章,主要讲解Android的事件分发流程,结合上一篇的绘制等流程,基本就可以掌握自定义view的核心内容。后续我会写一...
  • zuguorui
  • zuguorui
  • 2017年08月08日 23:27
  • 333

android 事件传递机制

总则: 1.onInterceptTouchEvent中有个Intercept,这是什么意思呢?她叫拦截,你大概知道她作用了吧,她就是你的亲亲小秘书,有什么事,先找秘书,秘书来决定这个事要不要你...
  • jks456
  • jks456
  • 2015年01月01日 11:45
  • 488

【Android】事件传递机制

未完,待续
  • u010119170
  • u010119170
  • 2014年09月30日 22:53
  • 329

Android点击事件传递机制详解

在讲正题之前我们讲一段有关任务传递的小故事,抛砖迎玉下: 话说一家软件公司,来一个任务,分派给了开发经理去完成: 开发经理拿到,看了一下,感觉好简单,于是 开发经理:分派给了开发组长 开发组长:分...
  • RuingMan
  • RuingMan
  • 2016年05月16日 15:45
  • 3360

android key事件分发与焦点事件的传递

andorid KeyEvent的传递流程和焦点的关系
  • hierophantzw
  • hierophantzw
  • 2017年03月10日 16:53
  • 760
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android事件传递机制
举报原因:
原因补充:

(最多只允许输入30个字)