[cocos2d-x] Director setNotificationNode 无点击事件

ui::Layout *layer = ui::Layout::create();
layer->setTouchEnabled(true);

Director::getInstance()->setNotificationNode(layer);

layer以及子控件接收不到点击事件,网上看了下同类问题,layer->onEnter()解决不了问题。

你这里用了UI的封装,不知道有没有bug,正常情况调用onEnter之后,NotificationNode是一定会收到event的。下面贴出一个示例:
定义:
typedef std::function<bool()> msCb;
class MsgBox: public Layer
{
public:
bool init(GLfloat width, GLfloat height);

void active();

inline void remove() {Director::getInstance()->setNotificationNode(nullptr);}

MsgBox():_action(nullptr), _callback(nullptr) {}

~MsgBox() {this->onExit();}

protected:
virtual void menuOnClick(Ref *sender) = 0;

Action *_action;
msCb _callback;

};

实现:
bool MsgBox::init(GLfloat width, GLfloat height)
{
if (!Layer::init()) return false;

setContentSize(Size(width, height));

return true;

}

void MsgBox::active()
{
Director::getInstance()->setNotificationNode(this);

this->onEnter();

if (_action)
    this->runAction(_action);

}
重载的virtual void menuOnClick(Ref *sender) = 0;是用来捕捉关闭事件,大概实现如下:
void ConnFailedMsg::menuOnClick(Ref *sender)
{
if (_callback && _callback())
this->remove();
}
如果回调函数的处理结果为true,则删除notification node。否则一直显示。
可以根据自己的需求做修改。

你用的什么版本的cocos2d-x,我这里即使手动调一次onEnter(),也没有收到按钮事件。

你调试下就知道问题在哪里了。
接受事件的处理逻辑:
l->isEnabled() && !l->isPaused() && l->isRegistered()&& onEvent(l)
即监听事件的node必须是enable、非pause、已注册才能进入onEvent的事件处理。

在你UI的layer加载后,在CCDirector.cpp的drawScene函数的
// draw the notifications node
if (_notificationNode)
{
_notificationNode->visit(_renderer, Mat4::IDENTITY, 0);
}
处打个断点,就可以看到你设置的notificationNode的状态是否正确:
isEnabled() && !l->isPaused() && l->isRegistered()

如果不正确,调用onEnter,
onEnter里面会调用:
this->resume();
_running = true;
使得isEnabled() && !l->isPaused() 为真。
l->isRegistered()就看你是否注册了事件。

为了排除UI封装的问题,你自己写个layer测试下就知道了。也可以手动触发一个事件,不是非要用引擎的menu来模拟。

我看另外一篇文章说,notificationLayer 的 isPause = true 的,在里面做schedule 之类的操作,是无法执行的。

“由于没有加入到场景中,因此isRunning始终为NO。这样CCScheduler便无法执行updatePosition这个方法,因为它的isPause==YES。”

最后怎么解决的?我用这个做个屏蔽层,都不能屏蔽触摸

我版本是3.3,在网上查找,发现有个bug,在
void Director::setNotificationNode(Node *node)
{
if(_notificationNode){
_notificationNode->onExit();
}
CC_SAFE_RELEASE(_notificationNode);
_notificationNode = node;
CC_SAFE_RETAIN(_notificationNode);
if(_notificationNode){
_notificationNode->onEnter();
}
}
缺少了onEnter函数,另外在 Director::~Director(void)
if (_notificationNode) {
_notificationNode->onExit();
_notificationNode->cleanup();
_notificationNode->release();
}
,这样就正常了