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的更多相关文章

  1. iOS学习笔记之触摸事件&UIResponder

    iOS学习笔记之触摸事件&UIResponder 触摸事件 与触摸事件相关的四个方法如下: 一根手指或多根手指触摸屏幕 -(void)touchesBegan:(NSSet *)touches ...

  2. Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行

    Ext.Net学习笔记16:Ext.Net GridPanel 折叠/展开行 Ext.Net GridPanel的行支持折叠/展开功能,这个功能个人觉得还说很有用处的,尤其是数据中包含图片等内容的时候 ...

  3. SQL反模式学习笔记16 使用随机数排序

    目标:随机排序,使用高效的SQL语句查询获取随机数据样本. 反模式:使用RAND()随机函数 SELECT * FROM Employees AS e ORDER BY RAND() Limit 1 ...

  4. golang学习笔记16 beego orm 数据库操作

    golang学习笔记16 beego orm 数据库操作 beego ORM 是一个强大的 Go 语言 ORM 框架.她的灵感主要来自 Django ORM 和 SQLAlchemy. 目前该框架仍处 ...

  5. 一个demo让你彻底理解Android中触摸事件的分发

    注:本文涉及的demo的地址:https://github.com/absfree/TouchDispatch 1. 触摸动作及事件序列 (1)触摸事件的动作 触摸动作一共有三种:ACTION_DOW ...

  6. Android学习笔记点击事件和触摸事件的区别

    当我们点击手机屏幕的时候Android系统不仅会触发单击事件,还会触发触摸事件.在Android中它会先触发触摸事件,如果这个触摸事件没有被消费掉再去触发单击事件 代码示例: MainActivty. ...

  7. iOS学习笔记07-运动事件和远程控制

    之前我们已经学习了触摸处理和手势识别,其实这两个同属于iOS事件的触摸事件,今天我们来学习下iOS事件的另外两个事件: 一.运动事件 运动事件,是通过加速器进行触发,和触摸事件一样,继承UIRespo ...

  8. 微信小程序学习笔记二 数据绑定 + 事件绑定

    微信小程序学习笔记二 1. 小程序特点概述 没有DOM 组件化开发: 具备特定功能效果的代码集合 体积小, 单个压缩包体积不能大于2M, 否则无法上线 小程序的四个重要的文件 *js *.wxml - ...

  9. AngularJS1.X学习笔记4-内置事件指令及其他

    AngularJS为我们定义了一系列事件指令,方便我们对用户的操作作出响应.甚至他还有一个可选模块提供了触摸事件和手势事件的支持,为移动端开发提供了可能.现在开始学习一下AngularJS的事件指令. ...

随机推荐

  1. 多线程——Runnable接口

    以实现Runable接口的方式创建线程比继承Thread类有很大的优越性,因为类不能多重继承,即一个类只能继承一个类,那么如果该类已经继承了一个类,就不能实现多线程了,但是可以通过实现Runable接 ...

  2. iOS上架的整体流程和建议

    App Store上架指的是iOS应用从提交申请到上线的整个过程,它的目的是让应用展示在App Store上获取流量.用户. 一.iOS上架的整体流程 1.申请开发者账号 苹果的开发者账号主要分为三种 ...

  3. 关于WebApi的跨域问题

    前端调用我后端接口时出现200,跨域问题 解决方案: 在webconfig中加入以下配置就OK了 <configuration> <system.webServer> < ...

  4. 搭建Android+QT+OpenCV环境,实现“单色图片着色”效果

               OpenCV是我们大家非常熟悉的图像处理开源类库:在其新版本将原本在Contrib分库中的DNN模块融合到了主库中,并且更新了相应文档.这样我们就能够非常方便地利用OpenCV实 ...

  5. Leetcode 121.买股票的最佳时机

    题目描述: 给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出 ...

  6. 云原生生态周报 Vol. 21 | Traefik 2.0 正式发布

    作者 | 浔鸣.心水.元毅.源三.衷源 业界要闻 CNCF 计划将 TOC 升至 11 人 技术监督委员会(TOC)是 CNCF 的三大核心管理机构之一,从 2020 年 1 月起,TOC 将从 9 ...

  7. MybatisPlus报错Invalid bound statement (not found)的解决方案

    今天使用MybatisPlus,测试时报错Invalid bound statement (not found) 使用自定义的mapper接口中的方法可以执行,而调用MybatisPlus中baseM ...

  8. Django+MySQL Dashboard 网页端数据库可视化

    1. Overview Python+MySQL+Django, 有些数据托管在 MySQL 的数据库,然后我们希望进行可视化,通过 web 的方式对数据库的信息去进行展示/检索/维护/.. 这个项目 ...

  9. RocketMQ学习 -> NameServer路由中心

    RocketMQ项目代码核心目录说明 broker:broker启动进程 client:消息客户端,包含消息生产者,消息消费者相关类 common:公共包 dev:开发者信息(非源代码) distri ...

  10. .net core 3.0 Signalr - 06 业务实现-业务分析

    ## 业务需求 1. 人-项目关系 一个人可以属于多个项目,一个项目可以有多个人加入,通知的时候,可以通知项目内的所有人,也可以通知部分人或者某个责任人. 2. 登录互斥 同一个人不允许登录两次(不同 ...