关于CCControlSwitch设置在弹窗上后的触摸优先级问题

在最近的工程中,由于游戏中设置场景的东西很少,所以决定没必要写成一个场景,并且写成场景后有切换场景时出现的释放资源问题,最终决定用模态弹窗来写。同样,我们先看看最终效果:


前面亮的就是弹出框,后面的就是模态化的背景。

关于模态的做法以及屏蔽下层按钮的做法,建议大家先去看泰然网的这篇文章,里面讲得非常详细并且附带源码:http://www.ityran.com/archives/4854


这里我们主要讲关于CCControlSwitch的问题,也就是图片中这样的按钮的问题。

按照以前弹出框的做法,弹出框上的按钮成功响应并且下层菜单被屏蔽,但是我发现CCControlSwitch按钮竟然也无法被响应,因为之前我们的“设置”是写成一个场景的,在场景中,同样的CCControlSwitch是能够被响应的,所以肯定不是他本身的问题,也就是说,它不能被响应的原因是被屏蔽掉了,因为在调试的时候我也试过调用CCControlSwitch的回调函数,发现没有响应,所以我确定它的确被屏蔽掉了,现在我们来看一下源码“

// 我把设置位置和设置Tag什么的都注释掉,大家只需要关心重点即可
void HSet::initSetMenu()
{
	// 这里手动设置触摸优先级,默认菜单是-128,只要比-128大的值(-127),都可以屏蔽下层菜单的触摸,
	// 这里设置为-128类似于addChild()函数中的zOrder,虽然值一样,但是之后添加的都将覆盖之前的。
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);
	// 设置透明度,需要继承CCLayerColor而不是CCLayer
	this->setOpacity(150);
	CCSize visibleSize = PublicMethod::getVisibleSize();
	CCPoint origin = PublicMethod::getOrigin();
	// 这是弹出对话框
	CCSprite* setDialog = CCSprite::create("/Set/NB_SetDialog.png");
	//setDialog->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));

	// 音乐和音效的图标
	CCSprite* music_Icon = CCSprite::create("/Set/NB_Music_Icon.png");
	CCSprite* effect_Icon = CCSprite::create("/Set/NB_Effect_Icon.png");
	//music_Icon->setPosition(ccp(music_Icon->getContentSize().width, setDialog->getContentSize().height/2));
	//effect_Icon->setPosition(ccp(effect_Icon->getContentSize().width, setDialog->getContentSize().height/2 - effect_Icon->getContentSize().height - SET_MENU_ITEM_OFFSET));
	setDialog->addChild(music_Icon, 0);
	setDialog->addChild(effect_Icon, 0);

	// “用户协议”按钮和“开发人员”按钮
	CCMenuItemImage* userAgreementButton = CCMenuItemImage::create("/Set/NB_UserAgreement_Normal.png", "/Set/NB_UserAgreement_Select.png", this, NULL);
	CCMenuItemImage* producerButton = CCMenuItemImage::create("/Set/NB_Producer_Normal.png", "/Set/NB_Producer_Select.png", this, NULL);
	CCMenuItemImage *setBackButton = CCMenuItemImage::create("/Shop/NB_CardBack_Normal.png", "/Shop/NB_CardBack_Select.png", this, menu_selector(HSet::backIsPressed));
	//userAgreementButton->setTag(set_itemUserAgreementTag);
	//producerButton->setTag(set_itemProducerTag);
	//setBackButton->setTag(set_itemBackTag);
	//userAgreementButton->setPosition(ccp(userAgreementButton->getContentSize().width/2 + SET_MENU_ITEM_OFFSET, 0));
	//producerButton->setPosition(ccp(producerButton->getContentSize().width/2 + SET_MENU_ITEM_OFFSET, -producerButton->getContentSize().height - SET_MENU_ITEM_OFFSET/2));
	//setBackButton->setPosition(ccp(setDialog->getContentSize().width/2 - setBackButton->getContentSize().width + SET_BACK_OFFSET_X, setDialog->getContentSize().height/2 - setBackButton->getContentSize().height + SET_BACK_OFFSET_Y));
	CCMenu* set_menu = CCMenu::create(producerButton, userAgreementButton, setBackButton, NULL);
	//set_menu->setPosition(ccp(setDialog->getContentSize().width/2, setDialog->getContentSize().height/2));
	setDialog->addChild(set_menu, 0, set_menuTag);

	// 设置音乐和音效的开关按钮,这里是重点
	// 我在开关按钮下面添加了一个白底,不重要但是这样比较好看。
	CCSprite* musicSwitcherBoard = CCSprite::create("/Set/NB_Switch_Board.png");
	//musicSwitcherBoard->setPosition(ccp(music_Icon->getContentSize().width/2 + musicSwitcherBoard->getContentSize().width, music_Icon->getPositionY()));
	//musicSwitcherBoard->setTag(musicSwitcherBoardTag);
	setDialog->addChild(musicSwitcherBoard, 0);
	// 这里我们就在添加音乐的开关按钮
	CCControlSwitch *musicSwitcher = CCControlSwitch::create(
		CCSprite::create("/Set/NB_Switch_Mask.png"), CCSprite::create("/Set/NB_Switch_On.png"),
		CCSprite::create("/Set/NB_Switch_Off.png"),	CCSprite::create("/Set/NB_Set_Cursor.png"));
	//musicSwitcher->setPosition(ccp(musicSwitcherBoard->getContentSize().width/2, musicSwitcherBoard->getContentSize().height/2));
	//musicSwitcher->setTag(musicSwitcherTag);
	musicSwitcherBoard->addChild(musicSwitcher,0);

	// 这里添加音效的开关按钮,和音乐一样,我就不写了
	// ..............................................
	
	// 再把整个对话框添加上去
	this->addChild(setDialog, 0, setDialogTag); 
}

这样我们的初版弹出设定框就写好了,效果就和之前那个图一样,但是会发现,CCControlSwitch不能响应。于是经过各种跟踪代码调试等方法我找到了问题的所在,也就是上面所说的被屏蔽的问题。即:CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);这句代码搞的鬼。

大体来讲就是因为CCControlSwitch是继承自CCControl,CCControl又是继承自CCLayer,而CCMenuItem是继承自CCNode,两个的触摸级别本来就不是一样的,大家可以分别获取一下它们的触摸级别,CCControlSwitch在设置之前是1,而CCMenuItem是-128,所以要分开设置。单步调试的话还有更细节的东西,这里我就不细讲了,直接给出解决方案:

在musicSwitcher创建后再手动设置其优先级,同样是-128

musicSwitcher->setTouchPriority(-128);
这样CCControlSwitch就能够被正常响应,但之后还会报一个错误,我的弹出框是从主界面弹出的,在我点击返回以后,再点击主界面的任何一个地方,都会报一个CCNode的错误,出现这种错误就是因为弹出层返回时没有销毁CCControlSwitch,虽然在我的代码里当设定选单返回后会调用removeFromParent();这样一句函数,但依然是不够的,我们还需要调用tem_musicSwitcher->removeFromParentAndCleanup(true);这样一句函数来手动销毁CCControlSwitch。

OK,这样我们就完成了一个带CCControlSwitch的弹出设定框,大家还可以给弹出设定框写一些特效来丰富它,至于特效怎么写,就留在下一次博客写吧。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值