简介
- cocos的事件分发机制,先创建事件,然后注册到事件管理中心_eventDispatcher,通过发布事件得到响应进行回调,完成事件流。
- _eventDispatcher是Node的属性,通过它管理当前节点(场景、层、精灵等)的所有事件的分发。但它本身是一个单例模式值的引用,在Node的构造函数中,通过Director::getInstance()->getEventDispatcher() 获取,有了这个属性,就能方便的处理事件。
事件相关的类
Event (基类)
EventCustom (自定义事件)
EventTouch (触摸事件)
EventMouse (鼠标事件)
EventKeyboard (键盘事件)
EventFocus (控件获取焦点事件)
EventAcceleration (加速计事件)
事件监听器
EventListener, EventListenerCustom, EventListenerFocus, EventListenerMouse, EventListenerTouch, EventListenerKeyboard, EventListenerAcceleration
事件分发器
EventDispatcher (事件分发机制逻辑集合体)
事件监听器的创建与监听
创建:直接new一个Event的子类即可。
监听:添加事件监听器有三个方法,都在 EventDispatch 类中,分别是:
void addEventListenerWithSceneGraphPriority(EventListener* listener, Node* node);
void addEventListenerWithFixedPriority(EventListener* listener, int fixedPriority);
EventListenerCustom* addCustomEventListener(const std::string &eventName, const std::function<void(EventCustom*)>& callback);
事件的优先级
- 优先级越低,越先响应事件
- 如果优先级相同,则上层的(z轴)先接收触摸事件。
void EventDispatcher::dispatchEvent(Event* event)
{
if (!_isEnabled)
return;
updateDirtyFlagForSceneGraph();
DispatchGuard guard(_inDispatch);
// 如果是触摸事件,走这里
if (event->getType() == Event::Type::TOUCH)
{
//该方法介绍了单指多指的优先逻辑(先走单指,再走多指)
dispatchTouchEvent(static_cast<EventTouch*>(event));
return;
}
// 先通过event获取到事件的标志ListenerID
auto listenerID = __getListenerID(event);
// 排序此事件的所有的监听器
sortEventListeners(listenerID);
// 分发事件逻辑的函数指针
auto pfnDispatchEventToListeners = &EventDispatcher::dispatchEventToListeners;
if (event->getType() == Event::Type::MOUSE) {
// 如果是鼠标事件重新赋值分发事件的函数指针
pfnDispatchEventToListeners = &EventDispatcher::dispatchTouchEventToListeners;
}
// 获取改事件的所有的监听器
auto iter = _listenerMap.find(listenerID);
if (iter != _listenerMap.end())
{
// 如果有,取出里面监听器的Vector
auto listeners = iter->second;
// 找到对应的监听器的时候会触发的回调函数
auto onEvent = [&event](EventListener* listener) -> bool{
event->setCurrentTarget(listener->getAssociatedNode());
// 触发onEvent回调
listener->_onEvent(event);
return event->isStopped();
};
// 调用函数指针分发事件
(this->*pfnDispatchEventToListeners)(listeners, onEvent);
}
updateListeners(event);
}
void EventDispatcher::dispatchEventToListeners(EventListenerVector* listeners, const std::function<bool(EventListener*)>& onEvent)
{
bool shouldStopPropagation = false;
auto fixedPriorityListeners = listeners->getFixedPriorityListeners();
auto sceneGraphPriorityListeners = listeners->getSceneGraphPriorityListeners();
ssize_t i = 0;
// priority < 0 优先处理priority小于0的时候的事件监听器
if (fixedPriorityListeners)
{
CCASSERT(listeners->getGt0Index() <= static_cast<ssize_t>(fixedPriorityListeners->size()), "Out of range exception!");
if (!fixedPriorityListeners->empty())
{
for (; i < listeners->getGt0Index(); ++i)
{
auto l = fixedPriorityListeners->at(i);
// 判断是否可以执行事件,如果可以最后调用onEvent执行,如果onEvent返回true,说明吞噬事件,结束分发。
if (l->isEnabled() && !l->isPaused() && l->isRegistered