Cocos2d-x 学习笔记(16) 触摸事件与分发 EventTouch dispatchTouchEvent EventListenerTouch
1. EventTouch
触摸事件的成员变量:枚举EventCode、存储Touch的容器。
不同的EventCode代表不同时机的触摸事件,能让监听器调用不同的回调函数。
enum class EventCode
{
BEGAN,
MOVED,
ENDED,
CANCELLED
};
static const int MAX_TOUCHES = 15;
EventCode _eventCode;
std::vector<Touch*> _touches;
这里涉及到了Touch类:
Touch类
封装了一个触摸信息,包括触摸点类型(单点/多点)、坐标、开始坐标、ID、3D触控压力等。有set get方法。
2. EventListenerTouch
触摸事件监听器根据触摸点touch类型的不同,分为单点触摸监听器/多点触摸监听器。
2.1 EventListenerTouchOneByOne
单点触摸监听器回调函数只能处理触摸事件中一个touch。
ID统一为:
const std::string EventListenerTouchOneByOne::LISTENER_ID = "__cc_touch_one_by_one";
该类4个回调函数,根据触摸事件code不同分类:
public:
typedef std::function<bool(Touch*, Event*)> ccTouchBeganCallback;
typedef std::function<void(Touch*, Event*)> ccTouchCallback;
ccTouchBeganCallback onTouchBegan; //开始触摸
ccTouchCallback onTouchMoved; //触摸并移动
ccTouchCallback onTouchEnded; //结束触摸
ccTouchCallback onTouchCancelled; //触摸取消
该类2个成员变量:
private:
std::vector<Touch*> _claimedTouches; //存储处理完BEGAN事件的回调函数的参数touch
bool _needSwallow; //事件需要吞没,为true时停止事件向其他监听器分发,setSwallowTouches(bool)设置,默认为false
在add监听器到分发器时,首先需要对该监听器执行checkAvailable()。单点触摸监听器的checkAvailable()中,要求onTouchBegan需要存在。
2.2 EventListenerTouchAllAtOnce
多点触摸监听器回调函数能一次处理事件中所有touch。
ID为:
const std::string EventListenerTouchAllAtOnce::LISTENER_ID = "__cc_touch_all_at_once";
4个回调函数:
public:
typedef std::function<void(const std::vector<Touch*>&, Event*)> ccTouchesCallback;
ccTouchesCallback onTouchesBegan;
ccTouchesCallback onTouchesMoved;
ccTouchesCallback onTouchesEnded;
ccTouchesCallback onTouchesCancelled;
checkAvailable()方法要求4个回调函数都要存在。
3. dispatchTouchEvent
在dispatchEvent方法中,当参数事件为TOUCH类型,调用dispatchTouchEvent进行事件分发。
该方法首先对2个触摸监听器ID的容器Vector按优先级排序,之后获取触摸事件中所有touch,用容器保存:

如果2种监听器都存在,isNeedsMutableSet置true。
然后对单点触摸监听器分发事件
单点触摸事件分发的逻辑是,把触摸事件的每个touch依次传给所有排好序的单点触摸监听器,监听器执行定义的匿名函数,而不是监听器自带的_onEvent(单点触摸监听器init时_onEvent置nullptr)。

每个单点触摸监听器执行的回调函数运行流程大致如下:
简而言之,根据触摸事件code决定执行哪种回调函数,开始触摸对应的回调函数处理touch,对处理好的touch存储到监听器容器,以便还是该监听器执行后续的移动触摸/结束触摸的回调。移动触摸对应的回调函数处理touch。结束触摸对应回调函数处理touch,并从监听器touch容器删除开始触摸的touch,说明整个触摸流程结束了。

我们知道,当某个监听器的回调函数返回true时,事件将停止分发到后续监听器。
在单点触摸的监听器中,回调函数返回true时有2个情况:触摸事件停止/触摸事件被回调函数处理完成+已注册+监听器设置true吞没标志。
在单点触摸的监听器中,回调函数返回false时有这些情况:开始触摸的回调函数没有处理完事件/监听器对开始触摸没有回调方法/移动或结束触摸事件分发到无(对应的)开始触摸数据的监听器。
当事件停止,会直接退出当前分发,结束分发。
接下来对多点触摸监听器分发事件
多点触摸事件分发的逻辑是,每个需要多点触摸的touch已经存储在容器mutableTouches中,容器传给所有排好序的多点触摸监听器,监听器执行定义的匿名函数,而不是监听器自带的_onEvent(多点触摸监听器init时_onEvent置nullptr)。
单点触摸是将每个touch依次分发到所有监听器,多点触摸是将所有touch分发到所有监听器。
分发到事件的多点触摸监听器的匿名回调函数:通过对触摸事件code的判断,决定要执行自己监听器的哪个回调函数。当事件停止返回true,停止后续监听器接收事件。
4. 触摸事件分发时的Touch*容器 originalTouches mutableTouches
两个容器开始时都存储了本触摸事件的所有touch。
事件分发到单点触摸监听器,是遍历originalTouches,获取每个touch,再分发touch到监听器。
单点触摸回调函数中,如果一个touch在某个单点触摸监听器中处理完成,且_needSwallow为true,且存在多点触摸监听器,此时要从mutableTouches删除该touch。原因是_needSwallow为true说明本touch处理完后不再继续分发,而mutableTouches是需要分发到多点触摸监听器,故从mutableTouches中删除该touch。mutableTouches中的迭代器自动指向下一位。同时isSwallowed置true,即不用执行++mutableTouchesIter,迭代器已经实现了++操作。
还是上面的情况,如果没有多点触摸监听器,isSwallowed默认false,匿名回调函数返回true,停止本touch分发。接下来执行++mutableTouchesIter,和originalTouches一致。
简而言之,mutableTouches只在有多点触摸监听器的情况下可能发挥它独特的作用(只保存需要接下来多点触发的touch),否则和originalTouches无异,只是存储所有touch而已。
if (isClaimed && listener->_isRegistered && listener->_needSwallow) //如果事件处理完成,监听器注册状态, 监听器吞没
{
if (isNeedsMutableSet) //单点多点触摸的监听器都有
{
mutableTouchesIter = mutableTouches.erase(mutableTouchesIter); //删除此触摸点信息
isSwallowed = true; //
}
return true;
}
if (!isSwallowed)
++mutableTouchesIter;
//接下来遍历下个touch
Cocos2d-x 学习笔记(16) 触摸事件与分发 EventTouch dispatchTouchEvent EventListenerTouch的更多相关文章
- iOS学习笔记之触摸事件&UIResponder
iOS学习笔记之触摸事件&UIResponder 触摸事件 与触摸事件相关的四个方法如下: 一根手指或多根手指触摸屏幕 -(void)touchesBegan:(NSSet *)touches ...
- Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行
Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...
- SQL反模式学习笔记16 使用随机数排序
目标:随机排序,使用高效的SQL语句查询获取随机数据样本. 反模式:使用RAND()随机函数 SELECT * FROM Employees AS e ORDER BY RAND() Limit 1 ...
- golang学习笔记16 beego orm 数据库操作
golang学习笔记16 beego orm 数据库操作 beego ORM 是一个强大的 Go 语言 ORM 框架.她的灵感主要来自 Django ORM 和 SQLAlchemy. 目前该框架仍处 ...
- 一个demo让你彻底理解Android中触摸事件的分发
注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOW ...
- Android学习笔记点击事件和触摸事件的区别
当我们点击手机屏幕的时候Android系统不仅会触发单击事件,还会触发触摸事件.在Android中它会先触发触摸事件,如果这个触摸事件没有被消费掉再去触发单击事件 代码示例: MainActivty. ...
- iOS学习笔记07-运动事件和远程控制
之前我们已经学习了触摸处理和手势识别,其实这两个同属于iOS事件的触摸事件,今天我们来学习下iOS事件的另外两个事件: 一.运动事件 运动事件,是通过加速器进行触发,和触摸事件一样,继承UIRespo ...
- 微信小程序学习笔记二 数据绑定 + 事件绑定
微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...
- AngularJS1.X学习笔记4-内置事件指令及其他
AngularJS为我们定义了一系列事件指令,方便我们对用户的操作作出响应.甚至他还有一个可选模块提供了触摸事件和手势事件的支持,为移动端开发提供了可能.现在开始学习一下AngularJS的事件指令. ...
随机推荐
- centos7上安装zookeeper
centos7上安装zookeeper 1 准备工作 1.准备服务器,本次安装采用 centos7系统.内存2G.存储60G的虚拟机服务器一台: 2.服务器安装java环境: 参考文章<cent ...
- 03 (OC)* UITableView优化
一:cell注册和初始化 1:不注册cell 2:注册类 3:注册nib 4:storyboard 二:核心思想 1:UITableView的核心思想是:cell的重用机制.UITbleView只会创 ...
- Vue学习之todolist组件拆分
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [Linux] CentOS 显示 -bash: vim: command not found
转载自:https://www.cnblogs.com/wenqiangwu/p/3288349.html i. 那么如何安裝 vim 呢?输入rpm -qa|grep vim 命令, 如果 vim ...
- [Linux] Linux中重命名文件和文件夹的方法(mv命令和rename命令)
原文链接 在Linux下重命名文件或目录,可以使用mv命令或rename命令,这里分享下二者的使用方法. mv命令既可以重命名,又可以移动文件或文件夹. 例子:将目录A重命名为B mv A B 例子: ...
- JavaScript之JSON&AJAX
今天为大家讲解JavaScript中非常流行的数据传输形式JSON和异步技术AJAX技术. 一 JSON JSON的全称是JavaScript Object Notation(js对象表示法),它是一 ...
- java.nio.ByteBuffer中的flip()、rewind()、compact()等方法的使用和区别
java.nio.ByteBuffer 1. ByteBuffer中的参数position.limit.capacity.mark含义: position:表示当前指针的位置(下一个要操作的数据元素的 ...
- APP功能测试要点
1.功能性测试 根据产品需求文档编写测试用例而进行测试,包括客户端的单个功能模块以及功能业务逻辑(功能交互)如:涉及输入的地方需要考虑等价类,边界值,异常或非法等 1.1 安装与卸载测试 >软件 ...
- 接口测试返回数据为JSONP格式时如何处理
#需要被处理的jsonp数据 JSONP = "jsonpreturn({'c': 1, 'd': 2});" #处理方法 def jsonp_to_json(JSONP): JS ...
- Vertx Future 异常处理
Vertx Future 异常处理 异常发生 在使用Vertx进行开发的时候,必不可免使用Future异步编程框架.通过Future的 compose ,可以轻松实现不同异步任务的组合. 但是 ...