上一篇已经实现了如何建立一个模态对话框和非模态对话框,但是在手机上有时候【确认】或者【取消】按钮会非常难点击,无法关闭对话框,有时候,对话框可能仅仅是一个提示的作用 玩家可能想要只要点击其他地方就可以关闭掉对话框。下面就对这种对话框进行实现。
首先,这样对话框的模式就不只是模态对话框和非模态对话框两种模式了,我们就需要用到强类型的枚举变量,这种在3.X版本上也是常见的,比如
TouchEventType::ENDED
这样的变量,下面就做一个这样的枚举变量:
enum class Dialog_Model
{
Model = 0, //模态对话框
UnModel, //非模态对话框
TouchClear //点击其他地方自动清除对话框
};
当然对话框的函数也要稍微改变一下:
/* 加载对话框
* @parm:msg 消息 显示在界面上的提示消息
* @parm:fun 回调函数 给确定按钮调用的
* @parm:isNeedCancel 是否需要取消按钮
* @parm:Model 对话框模式
*/
void LoadDialog(std::string msg,std::function<void(Ref*)> fun,int isNeedCancel = false,Dialog_Model dialogModel = Dialog_Model::Model);
然后是实现方法:
//加载对话框
void MomoScene::LoadDialog(std::string msg,std::function<void(Ref*)> fun,int isNeedCancel,Dialog_Model dialogModel)
{
Dialog->setVisible(true);
Dialog->getAnimation()->playWithIndex(0);
Dialog->getAnimation()
->setMovementEventCallFunc(CC_CALLBACK_3(MomoScene::LoadDialogFinish,this));
m_DialogMsg->setString(msg);
m_Dialog_ConfirmCallback = fun;
//是否需要关闭按钮
if(isNeedCancel == true)
{
m_DialogConfirm->addTouchEventListener(CC_CALLBACK_2(MomoScene::PressDialogConfirmBtn,this));
m_DialogCancel->addTouchEventListener(CC_CALLBACK_2(MomoScene::PressDialogCancelBtn, this));
m_DialogConfirm->setVisible(true);
m_DialogCancel->setVisible(true);
}
else
{
m_DialogConfirm->addTouchEventListener(CC_CALLBACK_2(MomoScene::PressDialogConfirmBtn,this));
m_DialogConfirm->setPosition(Point(0,-100));
m_DialogConfirm->setVisible(true);
m_DialogCancel->setVisible(false);
}
auto listener1 = EventListenerTouchOneByOne::create();//创建一个触摸监听
listener1->setSwallowTouches(true);//设置不想向下传递触摸
listener1->onTouchBegan = [](Touch* touch, Event* event){
CCLOG("touch Swallow");
return true;
};
//模态对话框需要做一个吞噬触摸层
if(dialogModel == Dialog_Model::Model)
{
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,m_UI_Dialog);
}
else if(dialogModel == Dialog_Model::TouchClear)
{
listener1->onTouchEnded = [&](Touch* touch, Event* event){
//只有点击对话框外面才关闭对话框
Rect rect = Dialog->getBoundingBox();
if(!rect.containsPoint(touch->getLocation()))
HideDialog();
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(listener1,m_UI_Dialog);
}
}
实现方法看起来是越来越臃肿了,不过只需要看后面几行就可以了,首先获取到对话框的碰撞区域,用getBoundingBox就可以得到它的碰撞区域,如果在碰撞区域内,即触摸结束点在盒子内,就不隐藏对话框。否则就隐藏。
还有,上次做的对话框有一个bug忘记了,就是在对话框关闭完成的时候忘记关闭触摸监听了,用下面的方法关闭即可
_eventDispatcher->removeEventListenersForTarget(m_UI_Dialog);
因为m_UI_Dialog中只有一个监听,就是屏蔽层,这样去掉的层就是屏蔽层了。
附上demo供大家研究: