文档章节

android事件分发机制总结

亓斌哥哥
 亓斌哥哥
发布于 2014/10/08 20:49
字数 1106
阅读 1K
收藏 18

行业解决方案、产品招募中!想赚钱就来传!>>>

Android事件分发机制

 

android 普通view(不包含ViewGroup)和activity中主要有一下两个方法处理事件:

public boolean dispatchTouchEvent(MotionEvent ev) // 分发事件
public boolean onTouchEvent(MotionEvent event)     // 处理事件

 

ViewGroup中还一个方法:

public boolean onInterceptTouchEvent(MotionEvent ev) // 拦截事件

 

1、activity中,顺序是:事件分发->事件处理,如果在事件分发时消费了某个事件(return true)则事件处理将不会接收到该事件。

 

public class MainActivity extends Activity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
// 事件分发
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if(ev.getAction() == MotionEvent.ACTION_MOVE) {
 System.out.println("dispatchTouchEvent-->ACTION_MOVE");
return true; // 表示我消费了,不继续分发
}
return super.dispatchTouchEvent(ev);
}
// 处理事件
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
System.out.println("onTouchEvent-->ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
System.out.println("onTouchEvent-->ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
System.out.println("onTouchEvent-->ACTION_UP");
break;
}
return super.onTouchEvent(event);
}
}

 

以上代码的结果:

onTouchEvent-->ACTION_DOWN

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

dispatchTouchEvent-->ACTION_MOVE

onTouchEvent-->ACTION_UP

 

从结果上看:ACTION_MOVE并没有到onTouchEvent中,因为我们在dispatchTouchEvent判断,如果是ACTION_MOVEreturn true表示消耗掉该事件,事件就不会分发到onTouchEvent中,所有onTouchEvent只能接收到ACTION_DOWNACTION_UP事件。

 

2、普通view的事件分发

 

一个普通view的事件由dispatchTouchEvent分发事件,事件的顺序是ACTION_DOWNACTION_MOVEACTION_UP,如果有一个事件被消费掉,其他的事件不会执行到;分发事件由onTouch首先接收到,如果onTouch返回true了,表示消费掉了该事件,那么该viewclick事件将不会执行。

 

mButton.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
  System.out.println("onTouch..."+event.getAction());
return true;  // 消费了该事件,下面的click事件不会执行
}
});
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 因为上面的onTouch把事件消费了,则这里执行不到
System.out.println("onClick...");
}
});

 

 

3、ViewGroup的事件分发:

ViewGroup的事件分发稍微麻烦点,以自定义的LinearLayout : MyLayout为例;

事件发生,首先由MyLayout的dispatchTouchEvent进行事件的分发
然后到MyLayout的onInterceptTouchEvent拦截事件
1、onInterceptTouchEvent如果return true表示拦截该事件,并在MyLayout中处理
剩下的事件,事件继续由MyLayout进行分发,分发机制同上面的view事件分发机制,但这次分发不会考虑分发给子view,也不会走onInterceptTouchEvent,因为系统已经知道
该套事件MyLayout已经拦截,所以直接在MyLayout中处理

2、如果MyLayoutonInterceptTouchEvent返回false(默认返回false[1]),表示不拦截事件,由MyLayout的子view(以Button为例)的dispatchTouchEvent开始分发事件,分发机制就是上面的view事件分发机制。

public class MyLayout extends LinearLayout {
	public MyLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}
	
	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		System.out.println("dispatchTouchEvent");
		return super.dispatchTouchEvent(ev);
	}
	
	
	// 事件发生, 首先由MyLayout的dispatchTouchEvent进行事件的分发
	// 然后到MyLayout的onInterceptTouchEvent拦截事件
	// 如果return true表示拦截该事件,并在MyLayout中处理
	// 剩下的事件继续由MyLayout进行分发,这次分发不会考虑分发给
	// 子view,也不会走onInterceptTouchEvent,因为系统已经知道
	// 该套事件MyLayout已经拦截,所以直接在MyLayout中处理
	
	// 该demo的执行结果:
	// 第一套down、move、up :
	// dispatchTouchEvent
	// onInterceptTouchEvent
	// action_down...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_up...
	
	// 再一套:
	// dispatchTouchEvent
	// onInterceptTouchEvent
	// action_down...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_move...
	// dispatchTouchEvent
	// action_up...
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		System.out.println("onInterceptTouchEvent");
		if(ev.getAction() == MotionEvent.ACTION_DOWN) {
			return true;
		}
		return super.onInterceptTouchEvent(ev);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			System.out.println("action_down...");
			break;
		case MotionEvent.ACTION_UP:
			System.out.println("action_up...");
			break;
		case MotionEvent.ACTION_MOVE:
			System.out.println("action_move...");
			break;
		}
		return true;
	}
}

执行的结果:

 第一套down、move、up :
dispatchTouchEvent
onInterceptTouchEvent
action_down...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_up...
 
再一套:
dispatchTouchEvent
onInterceptTouchEvent
action_down...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_move...
dispatchTouchEvent
action_up...

 

MyLinearLayout

public class MyLinearLayout extends LinearLayout{
public MyLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return true;  
// 这里返回true, 则拦截掉事件,不会再往子view传递,继续调用该view的dispachTouchEvent和onTouch
}
}

 

 

MainActivity:

public class MainActivity extends Activity {
private MyLinearLayout mLayout;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayout = (MyLinearLayout) findViewById(R.id.layout);
mButton = (Button) findViewById(R.id.click);
mLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
System.out.println("layout touch " + event.getAction());
return false;
}
});
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// 因为在MyLinearLayout中已经拦截了事件,所以这里不会输出
               System.out.println("button click...");
}
});
}
}

 

执行结果:

layout touch 0


注意[1] : ListViewonInterceptTouchEvent默认返回的是true,表示拦截了事件。所以在listView中的Button按照普通设置click的方法是不能点击的。


亓斌哥哥

亓斌哥哥

粉丝 29
博文 34
码字总数 12346
作品 13
莱芜
程序员
私信 提问
加载中
此博客有 1 条评论,请先登录后再查看。
Netty那点事(三)Channel与Pipeline

Channel是理解和使用Netty的核心。Channel的涉及内容较多,这里我使用由浅入深的介绍方法。在这篇文章中,我们主要介绍Channel部分中Pipeline实现机制。为了避免枯燥,借用一下《盗梦空间》的...

黄亿华
2013/11/24
2W
22
浅入浅出Android(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
636
1
程序猿媛一:Android滑动翻页+区域点击事件

滑动翻页+区域点击事件 ViewPager+GrideView 声明:博文为原创,文章内容为,效果展示,思路阐述,及代码片段。文尾附注源码获取途径。 转载请保留原文出处“http://my.oschina.net/gluoyer...

花佟林雨月
2013/11/09
4.2K
1
基于 ThinkPHP 的内容管理系统--歪酷CMS

歪酷网站管理系统(歪酷CMS)是一款基于THINKPHP框架开发的PHP+MYSQL网站建站程序,本程序实现了文章和栏目的批量动态管理,支持栏目无限分类,实现多管理员管理,程序辅助功能也基本实现了常见的文...

鲁大在线
2013/02/19
7K
1
Android3D应用与游戏开发框架--JQGL

JQGL 是一款针对Android设备上3D应用、游戏的开发框架。 核心功能是OpenGL-ES的使用框架,相对于大部分开发者而已,OpenGL是陌生的,没有专门研究无法进行相关的开发。 本框架针对于Android...

Jping
2013/02/21
1.6K
0

没有更多内容

加载失败,请刷新页面

加载更多

AI复原上海民国名媛影像!1929年的小姐姐,时装精致不输现在

萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 中国最早的时装秀,是什么样的? 自修复100年前的北京影像后,微博博主@大谷Spitzer这次又用AI工具,复原了民国时期的这场「花生骚」(Fashi...

视学算法
今天
22
0
【脑电硬件】教育相关的商业可穿戴脑电设备概览

脑电是一门古老的脑成像技术,但迄今为止也依然是最具生命力的主流脑成像技术之一。这主要得益于相比其他脑成像技术,脑电设备具有便携性好,使用成本低,无创,高时间分辨率,和丰富的频率信...

好未来技术
24分钟前
27
0
米菲云仓系统开发(米菲系统)

本章阐述持续集成系统的发展历程、持续集成系统的原理,以及持续集成系统的实现过程,目的是让大家全面了解持续集成系统,更加深入的学习持续集成系统的原理,为后续章节的学习做好准备。我会...

薇fzb246724
32分钟前
55
0
传统租车服务企业,拥抱Docker,K8s,微服务之路!

走进台湾双北市的民营停车场,现在有机会看到贴有Smart2go字样的车辆停在停车场,供租用,而无论预约、取车、还车到付款,使用一站式App都能完成。这是格上汽车租赁(简称格上)从今年4月开始...

Kubernetes
今天
23
0
2020年7月Github上最热门的开源项目

7月份GitHub上最热门的开源项目排行已经出炉啦,一起来看看上榜详情吧 1 tsunami-security-scanner https://github.com/google/tsunami-security-scannerStar 5830 tsunami-security-scanne...

不卖萌的邓肯
今天
14
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部