【 每日·槽】第2话 -- 模态窗口的制作(即屏蔽其他层的touch事件)

本节目纯属扯淡,如有得罪,还请。。。。。。有本事你来打我呀!!!

【 每日·槽】第2话 – 模态窗口的制作
每日槽,君甚屌,家翁可知?

今天来和大家讨论下模态窗口的制作,
开发环境:cocos2d-x 3.0 beta1 jsb,CocoStudio: v1.2.0.1
我使用 javascript语言,其他语言也差不多啦~
这里讲两种方式:1、使用 cocostudio 的UI编辑器制作界面。2、不用 cocostudio 而用 cocos2d 里的 Layer。

第一种方法:使用cocostudio:
在第一话中我稍微提了一下一种模态窗口的制作方式,就是将除了模态窗口的界面的其他界面setEnabled(false),但这样有两个缺点:1、需要改源码,将setEnabled隐藏控件的功能去掉。(写这个帖子的时候还不知道用setTouchEnabled就可以)2、其他界面多了的话挨个调用也麻烦。
今天说说另一种比较方便的办法。

现在ui编辑器里制作窗口,结构如下:
Panel
imageView
button
button
Panel下面挂了一张图片,图片下面挂了两个按钮。蓝色按钮是魔胎窗口后面的控件,用来测试是否可以点击到。

代码如下:

// 读取ui编辑器制作好的窗口。
this._msgBox = ccs.GUIReader.getInstance().widgetFromJsonFile(‘MsgBox.ExportJson’);

// 将Panel大小设置为屏幕大小。这样就能使玩家点不到本窗口后面的控件,起到了遮挡的作用。
var visibleSize = cc.Director.getInstance().getVisibleSize();
this._msgBox.setSize(visibleSize);

// 使Panel可以被点击,貌似也可以在UI编辑器里设定。
this._msgBox.setTouchEnabled(true);

// addChild第二个参数是ZOrder。ZOrder越大就越先响应,这是因为widget中使用了addEventListenerWithSceneGraphPriority来注册EventListener。具体见UIWidget.cpp 里的 void Widget::setTouchEnabled(bool enable) 函数。
this.addChild(this._msgBox, 1); // 这里保证 zorder 高于其他层的 zorder 就好。

第二种方法:使用Layer
如果你不用cocostudio,只用cocos2d-jsb的话,也可以。那就要用到 cc.registerTargetedDelegate 这个函数,这个函数现在只有jsb里可以用,-x里已经去掉。

cc.registerTargetedDelegate(-1, true, layer);
第一个参数是优先级,越低优先级越高。
(CCEventgListener.h里 _fixedPriority 的注释是 The higher the number, the higher the priority 这意思是数字越高优先级越高吗?这显然是写错了!)
第二个参数是是否吃掉消息,如果 onTouchBegan 返回true,才会吃。吃掉后其他界面就不能响应了。
第三个参数当然就是模态窗口的 layer 啦。

layer 的 onTouchBegan 函数里必须返回 true。
layer.onTouchBegan = function(){
cc.log(‘onTouchBegan!!!’);
return true;
}

哦了,初始将模态窗口设置为不显示,在需要的时候显示出来就可以了。

附上 cocos2d-x 的事件分发机制文档:https://github.com/cocos2d/cocos-docs/blob/master/manual/framework/native/input/event-dispatcher/zh.md

今天的【 每日·槽】就到这里,小伙伴们还在等什么,快开始制作自己的模态窗口吧!


往期回顾:

【 每日·槽】第1话 – 论setEnabled和setVisible
http://www.cocoachina.com/bbs/read.php?tid=181496

【 每日·槽】第2话 – 模态窗口的制作
http://www.cocoachina.com/bbs/read.php?tid=181959

【 每日·槽】第3话-- UITextField的七宗罪 http://www.cocoachina.com/bbs/read.php?tid=182207

【 每日·槽】第4话-- UI
TextField 中文字符的长度检测问题

http://www.cocoachina.com/bbs/read.php?tid=182207

每日·槽】第5话 – 2014CocoaChina春季开发者大会实吐
http://www.cocoachina.com/bbs/read.php?tid=194385

你这次怎么只讲东西不吐槽了:880:

还是zorder和触摸优先级融合一下比较好~~这样的话很多问题都被解决了

zorder和触摸优先级融合一下 是指?

别着急,吐槽明天会有的

:843:能不能提前透露点啊?

就是按照显示的顺序分发事件~

噢噢 是这样的。cocos2d-x 新增的 addEventListenerWithSceneGraphPriority 就是这样。cocostudio用的好像也是addEventListenerWithSceneGraphPriority。

而jsb里不能使用 listener,所以只能用 cc.registerTargetedDelegate 了,里面用的是 addEventListenerWithFixedPriority

:9: 居然打错字了~~~

我说的是按渲染顺序来作为事件响应顺序~~

敢问楼主何方神圣,给跪了。

叫我红领巾!

借楼问个问题,请问版主,按渲染顺序来作为事件响应顺序,是cocos2dx v2.2.2已经有的功能还是需要自己实现?搜索了下,没找到相关的帖子

引擎将来要实现的。目前的版本还未实现该功能。

好的,谢谢!

你说的 “按渲染顺序来作为事件响应顺序 ” 就是 这里https://github.com/cocos2d/cocos-docs/blob/master/manual/framework/native/input/event-dispatcher/zh.md 提到的 SceneGraphPriority 吧。

local layer = TouchGroup:create()
local widget = GUIReader:shareReader():widgetFromJsonFile(“widget.ExportJson”)
layer:addWidget(widget )
widget :setTouchEnabled(false)

请问楼主 是不是这样就可以屏蔽控件的touch响应

但我这么写还是能响应点击

是啊 是啊 不好意思 才看到。论坛提示不给力

请问一下 那么如果把 一个放在最上层的 layer 删除 我删除的时候有 引用指针的错误 是不是需要retain ? 我retain了 也有错误 不知道为什么

问题解决了吗?你用的 c++ 吗?怎么删除的呀,错误提示是什么?

你好,我想问一下为什么我这样写不行:
setting_Panel = dynamic_cast<UIPanel*>(GUIReader::shareReader()->widgetFromJsonFile(“Export/setting_panel/setting_panel.ExportJson”));
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
this->setting_Panel->setSize(visibleSize);
multiplex->setTouchEnabled(false);
this->setting_Panel->setTouchEnabled(true);
this->addChild(this->setting_Panel, 1);

其中setting_Panel 是我定义的UIPanel类;multiplex是我定义的CCLayerMultiplex,用来管理界面切换