弹出框及层的屏蔽功能实现

一般游戏都会用到弹出框(退出提示,设置,战斗胜利等),初学者都会遇到这类的问题。要做一个弹出框的效果可能相对比较简单,但在实际开发中常常会遇到一些麻烦,就是点击弹出框的部分背后的事件也会响应,仅仅是这样的效果达不到要求。

 

小编初学这个的时候也会遇到这类问题,常常的解决方式就是度娘。

 

网上的方式大都很繁琐,不易理解,还有就是版本年代久远现在不适用,(小编的版本是cocos2dx 3.10)。

 

比如网上流行的一种方式是创建场景,即在原场景中在创建一个场景实现弹框效果,然后改变触摸优先级的大小,优先对最外层的场景触摸。这种方法理论上会实现,但是小编作为一个初学者这种方式理解相对较难。另外创建场景的方式会多创两个文件(头文件,cpp文件),如果仅仅只是显示几个文字,这样的方式显得很累赘,无疑增加代码量。(个人见解,无意冒犯)。

 

我今天讲的就是用创建的层的方式创建一个弹出框,然后用层截断的方式屏蔽背后的触摸。

 

这里做了一个测试在原层上创建了一个精灵 ,可以点击拖动。一个(点击弹出层)的按钮,点击就会弹出第三图的灰色的层。

没有弹出层的时候可以拖动精灵的位置,弹出层出现后,屏蔽了背后的响应事件,就不能拖动了。

 

也许大家有疑问这与弹框有什么联系,这个弹出层的大小可以设置,可以设置成想要的大小。层上面可以添加东西,与原层的添加方式一样,这里我在弹出层上添加了一个按钮(右下角),点击可以关闭弹出层。这里设置弹出层的目的是屏蔽背后的事件响应,所有我这里的弹出层的大小与显示区域大小一样。

 

#include "TestCeng.h"

Scene* TestCeng::createScene()
{
	auto scene = Scene::create();
	auto layer = TestCeng::create();
	scene->addChild(layer);
	return scene;
}

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

	Size visibleSize = Director::getInstance()->getVisibleSize();
	Vec2 origin = Director::getInstance()->getVisibleOrigin();

	//顶部显示标签
	Dictionary* strings = Dictionary::createWithContentsOfFile("string.xml");
	const char * str;
	//获取string.xml文件键值
	str = ((String *)strings->objectForKey("cenglogo"))->getCString();
	auto label = Label::createWithSystemFont(str, "", 30);
	label->setPosition(Vec2(visibleSize.width / 2, visibleSize.height*0.85));
	this->addChild(label, 2);
	//创建可以移动的精灵
	auto spr = Sprite::create("HelloWorld.png");
	spr->setTag(1);
	spr->setScale(0.5);
	spr->setPosition(Point(visibleSize.width / 2, visibleSize.height / 2));
	this->addChild(spr);
	//创建底部按钮
	str = ((String *)strings->objectForKey("ceng"))->getCString();
	auto button = MenuItemFont::create(str, CC_CALLBACK_0(TestCeng::createLayer, this));
	auto menu = Menu::create(button, NULL);
	menu->setPosition(Point(visibleSize.width / 2, visibleSize.height*0.2));
	this->addChild(menu, 2);

	//添加触摸事件
	auto listener = EventListenerTouchOneByOne::create();
	listener->setSwallowTouches(true);
	listener->onTouchBegan = CC_CALLBACK_2(TestCeng::onTouchBegan, this);
	listener->onTouchMoved = CC_CALLBACK_2(TestCeng::onTouchMoved, this);
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, spr);
	
	
	return true;
}

void TestCeng::createLayer()
{

	Size visibleSize = Director::getInstance()->getVisibleSize();
	//创建一个弹出层
	auto layer = LayerColor::create(Color4B(100, 180, 180, 180));
	layer->setContentSize(visibleSize);//设置与可显示区域大小一样
	layer->setPosition(Vec2::ZERO);
	this->addChild(layer,3);
	//层上添加一个返回按钮
	auto button = MenuItemImage::create("fanhui.jpg", "fanhui.jpg", CC_CALLBACK_0(TestCeng::menuCloseCallback, this));
	button->setScale(0.2);
	auto menu = Menu::create(button, NULL);
	menu->setPosition(Point(layer->getContentSize().width*0.95, layer->getContentSize().height*0.05));
	layer->addChild(menu);

	//对该层添加触摸事件 用于屏蔽背后的触摸事件
	auto listener = EventListenerTouchOneByOne::create();
	listener->setSwallowTouches(true);
	//实现屏蔽
	listener->onTouchBegan = [=](Touch *touch, Event *event) {
		Point location = touch->getLocation();
		if(layer->getBoundingBox().containsPoint(location))
			return true;
	};
	//绑定layer的触摸事件
	Director::getInstance()->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, layer);
}
bool TestCeng::onTouchBegan(Touch *touch, Event *event)
{
	Point location = touch->getLocation();
	
	auto spr = (Sprite*)this->getChildByTag(1);
	if (spr->getBoundingBox().containsPoint(location))
		return true;
	return false;
}

void TestCeng::onTouchMoved(Touch *touch, Event *event)
{
	auto spr = (Sprite*)this->getChildByTag(1);
	spr->setPosition(spr->getPosition() + touch->getDelta());
}
void TestCeng::menuCloseCallback()
{
	this->removeChild(this->getChildByTag(2));
}

 

init方法里创建一个顶部标签,精灵,按钮,对精灵绑定监听事件,
点击按钮进入createLayer方法,创建一个与显示区域大小一样的层,层上添加了一个返回按钮,点击移除该层。

 

重点说的是listener监听事件 setSwallowTouches设置触摸不可穿透,用addEventListenerWithSceneGraphPriority方式绑定监听,分别对精灵和层绑定。不建议用优先级的方式绑定。把弹出层的Z轴设在最上面,然后它将显示在最外层,触摸事件发生在层上时,return true就返回了。


在弹出层的触摸事件Began里获取弹出层的大小并判断触摸点是否在层上,在层上就截断触摸,没有自然就不会响应。这样大家就可以任意设置弹出层的大小,实现某一区域的触摸截断了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值