您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x 3.2 如何屏蔽下层管理事件?

2014-08-31 18:08 253 查看
最近,到处面试好累,这阵子也是一直看书复习,没什么心情来写博客。

昨天面试问我如何屏蔽下层按钮的点击事件,我的回答是使用了一个空的item暂停的时候,item放在游戏层的上面,大小覆盖整个屏幕,弹出对话框,这样下层无法点击。然后暂停层,比item更高一级。但当时测试手机版,出了一些BUG,例如 暂停层出问题,多次暂停后,无法点击回游戏。

虽然说一开始是个解决办法,但终究还是不行的。

虽然一口一口跟面试官说着,但我还是放出了这个问题没有解决的话。然后面试官问我,你到现在还没解决。。我清楚已经被鄙视了。其实当时这个问题我解决了一天。。有的时候,寻找答案的过程很神奇,像今天,我不用一天就找到了答案。

好吧。。正题!

参考:
http://www.zaojiahua.com/shielding-touch.html
修改了下。

走起:

下面是触摸屏蔽层头文件:

#ifndef _SWALLOWTOUCH_H_
#define _SWALLOWTOUCH_H_
#include "cocos2d.h"
class SwallowTouch : public cocos2d::LayerColor
{
public:
	SwallowTouch(void);
	~SwallowTouch(void);
	
	virtual bool init();
	
	CREATE_FUNC(SwallowTouch);

	void menuCallBack(cocos2d::Ref* sender);

};
#endif // !_SWALLOWTOUCH_H_


CPP文件:

#include "SwallowTouch.h"
USING_NS_CC;

SwallowTouch::SwallowTouch(void)
{
}

SwallowTouch::~SwallowTouch(void)
{
}
bool SwallowTouch::init()
{
	if(!LayerColor::initWithColor(Color4B(100,100,100,50)))		
		return false;
	auto visible = Director::getInstance()->getVisibleSize();
	
	auto label = Label::createWithTTF("touch!","minipy.ttf",32);

	label->setPosition(Point(visible) / 2);

	this->addChild(label);
	
	label->setColor(Color3B::YELLOW);

	auto callback = [](Touch * ,Event *)	
	{	
		return true;		
	};
	auto listener = EventListenerTouchOneByOne::create();

	listener->onTouchBegan = callback;

	listener->setSwallowTouches(true);

	_eventDispatcher->addEventListenerWithSceneGraphPriority(listener,this);

	//_eventDispatcher->addEventListenerWithFixedPriority(listener,-1);

	auto itemS = MenuItemImage::create("CloseNormal.png","CloseSelected.png","",CC_CALLBACK_1(SwallowTouch::menuCallBack,this));
	
	auto sMenu = Menu::create(itemS,nullptr);
	
	this->addChild(sMenu);
	
	sMenu->setPosition(label->getPosition() - Point(0,100));

	return true;
}
void SwallowTouch::menuCallBack(cocos2d::Ref* sender)
{
	this->removeFromParentAndCleanup(true);
}


屏蔽原理:

通过设置listener->setSwallowTouches(true);监听的helloworld,传进来的this是HelloWold,这样,屏蔽层下面的按钮就都无法点击了。而自己层的按钮是可以点的。

这里我还写了接口//_eventDispatcher->addEventListenerWithFixedPriority(listener,-1); 也可以实现同样的屏蔽效果。不过这样会吞噬的屏蔽层,同时,屏蔽层的优先级比HelloWorld层的大,下层自然也被屏蔽了。。

下面看看HelloWorld类写了什么:

嗯,头文件就不用看了。就一个函数

#include "HelloWorldScene.h"
#include "SwallowTouch.h"
USING_NS_CC;

Scene* HelloWorld::createScene()
{
	Scene *scene = Scene::create();

	HelloWorld *layer = HelloWorld::create();

	scene->addChild(layer);

	return scene;
}

bool HelloWorld::init()
{
	if(!Layer::init())
		return false;

	auto size = Director::getInstance()->getWinSize();	
	
	Vector<MenuItem *> itemVector;

	for(int i=1;i<4;i++)
	{
		auto item = MenuItemImage::create("CloseNormal.png","CloseSelected.png");
	
		item->setTag(i);

		itemVector.pushBack(item);
	}

	auto menu1 = Menu::createWithArray(itemVector);
	
	menu1->alignItemsHorizontallyWithPadding(10);

	menu1->setPositionY(size.height*0.75);
	
	this->addChild(menu1);

	auto swallowTouch = SwallowTouch::create();
	
	this->addChild(swallowTouch);

	return true;
}


写了3个按钮,在按钮的最后加入了屏蔽层。

现在,我们来试下。点一下屏幕的按钮,发现上面三个是不能点的,点一下下面的按钮的,点了后,文字和下面的按钮都不见了。这个时候你会发现上面的三个可以点。



好了,关于使用cocostuido做的素材,我也测试出来了,写法跟上面基本没区别。此时更改的是上层的按钮,下层依然为手写的按钮。

修改SwallowTouch init中的代码:

<span style="white-space:pre">	</span>auto test = GUIReader::getInstance()->widgetFromJsonFile("second_1/second_1.ExportJson");
<span style="white-space:pre">	</span>this->addChild(test);

<span style="white-space:pre">	</span>Button* btn = (Button*)test->getChildByName("Button_1");
<span style="white-space:pre">	</span>btn->setPosition(Point(130,100));
<span style="white-space:pre">	</span>btn->addTouchEventListener(this,SEL_TouchEvent(&SwallowTouch::menuCallBack));


同时修改回调函数的参数:

void SwallowTouch::menuCallBack(cocos2d::Ref* sender,TouchEventType type)
{
	if (type != TouchEventType::TOUCH_EVENT_BEGAN)
	{
		return;
	}
	int tag = ((Button*)sender)->getTag();
	switch (tag)
	{
	case 8:
		this->removeFromParentAndCleanup(true);
		break;
	}
	//this->removeFromParentAndCleanup(true);

}


运行结果如图。



其实cocostudio按钮有很多坑。重叠的时候会产生可以点击的状态!!!当上下两层均为cocostudio作出来的时候,默认上层可以屏蔽下层。无需任何操作。如图



但是,左下角两个按钮,在屏蔽层出现的情况下,重叠部分居然可以点击!非重叠部分正常不能点击。。那么为什么重叠部分可以点击呢。。有什么办法解决。

其实解决的问题有三种:

1,在重叠部分设置一个空的ITEM,界面两层之间。

2.调整顶层的UI布局;

似乎都不是很硬的方法解决。

经过不断的思考与尝试,发现可以通过调用Director::getInstance()->getEventDispatcher()->pauseEventListenersForTarget(this,true);

在按钮返回的时候,必须在清除层前调用Director::getInstance()->getEventDispatcher()->resumeEventListenersForTarget(this->getParent(),true);

就可以解决此问题。效果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: