参考:http://blog.sina.com.cn/s/blog_705a5ff00101ox4s.html
谢谢上面的哥们。
在上面的基础上作了些调整,直接支持键盘手柄和触摸事件的屏蔽功能
直接上代码吧
#ifndef __H_POPUPLAYER_H__
#define __H_POPUPLAYER_H__
#include "cocos2d.h"
#include "cocos-ext.h"
class PopupLayer:public cocos2d::Layer
{
public:
PopupLayer();
~PopupLayer();
CREATE_FUNC(PopupLayer);
virtual bool init();
static PopupLayer *create(const char *backGroundImage);
//设置标题
void setTitle(const char *title, int fontSize = 20);
//设置文本内容,padding 为文字到对话框两边预留的距离,这是可控的,距上方的距离亦是如此
void setContentText(const char *text, int fontSize = 20, int padding = 50, int paddingTop = 150);
void setCallBackFunc(Ref *target, cocos2d::SEL_CallFuncN callfuncN);
void addButton(const char *normalImage, const char *selectedImage, const char *title, int tag = 0);
void setFocus(int index = 0);//设置第index个button高亮
virtual void onEnter();
virtual void onExit();
private:
//焦点index
int m_focusIndex;
//文字内容两边的空白区域
int m_contentPadding;
int m_contentPaddingTop;
Ref *m_callBackListener;
cocos2d::SEL_CallFuncN m_callBack;
//用 CC_SYNTHESIZE_RETAIN 定义Menu*类型变量m_pMenu, 并且定义 MenuButton 的set/get方法
CC_SYNTHESIZE_RETAIN(cocos2d::Menu*, m_pMenu, MenuButton);
CC_SYNTHESIZE_RETAIN(cocos2d::Sprite*, m_sfBackGround, SpriteBackGround);
CC_SYNTHESIZE_RETAIN(cocos2d::ui::Scale9Sprite*, m_s9BackGround, Sprite9BackGround);
CC_SYNTHESIZE_RETAIN(cocos2d::Label*, m_ltTitle, LabelTitle);
CC_SYNTHESIZE_RETAIN(cocos2d::Label*, m_ltContentText, LabelContentText);
//键盘/手柄事件
void onKeyUpKeyboard(cocos2d::EventKeyboard::KeyCode keycode, cocos2d::EventKeyboard * event);
void onKeyUpController(cocos2d::Controller *controller, cocos2d::EventController *event);
//响应事件
void buttonCallBack(Ref *pSender);
//设置button效果
void setHighLight();
//删除自己
void destroyFromParent();
//按下 确认\左\右键
void keyEnterEvent();
void keyLeftEvent();
void keyRightEvent();
};
#endif
===========================================================================
#include "PopupLayer.h"
USING_NS_CC;
PopupLayer::PopupLayer()
{
m_contentPadding = 0;
m_contentPaddingTop = 0;
m_callBackListener = nullptr;
m_callBack = nullptr;
m_pMenu = nullptr;
m_sfBackGround = nullptr;
m_s9BackGround = nullptr;
m_ltTitle = nullptr;
m_ltContentText = nullptr;
m_focusIndex = 0;
}
PopupLayer::~PopupLayer()
{
CC_SAFE_RELEASE(m_pMenu);
CC_SAFE_RELEASE(m_sfBackGround);
CC_SAFE_RELEASE(m_s9BackGround);
CC_SAFE_RELEASE(m_ltTitle);
CC_SAFE_RELEASE(m_ltContentText);
}
bool PopupLayer::init()
{
if (!Layer::init())
{
return false;
}
//半透明层
Size visibleSize = Director::getInstance()->getVisibleSize();
LayerColor *layerColor = LayerColor::create(Color4B(0, 0, 0, 100), visibleSize.width, visibleSize.height);
this->addChild(layerColor);
//初始化需要的Menu
Menu *menu = Menu::create();
menu->setPosition(Vec2::ZERO);
setMenuButton(menu);
屏蔽下层点击事件
//EventListenerTouchOneByOne *listener = EventListenerTouchOneByOne::create();
//listener->onTouchBegan = [](Touch *touch, Event *event)
//{
// return true;
//};
//listener->setSwallowTouches(true);
//_eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this);
//keyboard事件
auto keyEvent = EventListenerKeyboard::create();
keyEvent->onKeyReleased = [&](EventKeyboard::KeyCode keyCode, Event* event)
{
this->onKeyUpKeyboard(keyCode, (EventKeyboard *)event);
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(keyEvent, this);
//屏蔽下层cotroller事件
auto controllerEvent = EventListenerController::create();
controllerEvent->onKeyUp = [&](Controller *controller, int keycode, Event *event)
{
CCLOG("屏蔽下层cotroller事件 onkeyup");
this->onKeyUpController(controller, (EventController *)event);
};
_eventDispatcher->addEventListenerWithSceneGraphPriority(controllerEvent, this);
return true;
}
void PopupLayer::onKeyUpController(Controller *controller, EventController *event)
{
Controller::Key keycode = (Controller::Key)event->getKeyCode();
CCLOG("keycode====>%d", keycode);
switch (keycode)
{
case Controller::Key::BUTTON_A:
keyEnterEvent();
break;
case Controller::Key::BUTTON_B:
destroyFromParent();
break;
case Controller::Key::BUTTON_DPAD_DOWN:
case Controller::Key::BUTTON_DPAD_LEFT:
keyLeftEvent();
break;
case Controller::Key::BUTTON_DPAD_UP:
case Controller::Key::BUTTON_DPAD_RIGHT:
keyRightEvent();
break;
}
}
void PopupLayer::onKeyUpKeyboard(EventKeyboard::KeyCode keycode, EventKeyboard * event)
{
//CCLOG("PopupLayer::onKeyUpKeyboard->keycode[%d]", keycode);
switch (keycode)
{
case EventKeyboard::KeyCode::KEY_KP_ENTER:
keyEnterEvent();
break;
case EventKeyboard::KeyCode::KEY_ESCAPE:
destroyFromParent();
break;
case EventKeyboard::KeyCode::KEY_DOWN_ARROW:
case EventKeyboard::KeyCode::KEY_LEFT_ARROW:
keyLeftEvent();
break;
case EventKeyboard::KeyCode::KEY_UP_ARROW:
case EventKeyboard::KeyCode::KEY_RIGHT_ARROW:
keyRightEvent();
break;
default:
break;
}
}
PopupLayer* PopupLayer::create(const char *backGroundImage)
{
PopupLayer *popup = PopupLayer::create();
popup->setSpriteBackGround(Sprite::create(backGroundImage));
popup->setSprite9BackGround(ui::Scale9Sprite::create(backGroundImage));
return popup;
}
//标题
void PopupLayer::setTitle(const char *title, int fontSize)
{
Label *lbTitle = Label::createWithSystemFont(title, "Helvetica", fontSize);
lbTitle->setColor(Color3B(255, 0, 0));
this->setLabelTitle(lbTitle);
}
//内容
void PopupLayer::setContentText(const char *text, int fontSize, int padding, int paddingTop)
{
Label *lbText = Label::createWithSystemFont(text, "Helvetica", fontSize);
lbText->setColor(Color3B(255, 0, 0));
this->setLabelContentText(lbText);
m_contentPadding = padding;
m_contentPaddingTop = paddingTop;
}
//设置回调
void PopupLayer::setCallBackFunc(Ref *target, SEL_CallFuncN callFuncN)
{
m_callBackListener = target;
m_callBack = callFuncN;
}
//响应回调事件
void PopupLayer::buttonCallBack(Ref *pSender)
{
if (m_callBackListener && m_callBack)
{
(m_callBackListener->*m_callBack)((Node *)pSender);
}
destroyFromParent();
}
//添加按钮
void PopupLayer::addButton(const char *normalImage, const char *selectedImage, const char *title, int tag)
{
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 center = Vec2(visibleSize.width / 2, visibleSize.height / 2);
MenuItemImage *menuImage = MenuItemImage::create(normalImage, selectedImage, CC_CALLBACK_1(PopupLayer::buttonCallBack, this));
menuImage->setTag(tag);
menuImage->setPosition(center);
Label *lbFont = Label::createWithSystemFont(title, "Helevtica", 30);
lbFont->setColor(Color3B(255,0,0));
lbFont->setPosition(menuImage->getContentSize()/2);
lbFont->setTag(110);
menuImage->addChild(lbFont);
this->getMenuButton()->addChild(menuImage);
}
void PopupLayer::setFocus(int index)
{
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
if (index >= 0 && index < menuItem->getChildrenCount())
{
m_focusIndex = index;
}
}
}
void PopupLayer::setHighLight()
{
//按钮
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
Vector<Node *> vct;
vct.pushBack(menuItem->getChildren());
for (int i = 0; i < vct.size(); i++)
{
MenuItemImage *menuImage = (MenuItemImage *)vct.at(i);
Label *label = (Label*)menuImage->getChildByTag(110);
Label *lbFont = Label::createWithSystemFont(label->getString(), "Helevtica", 30);
lbFont->setColor(Color3B(255, 0, 0));
lbFont->setPosition(menuImage->getContentSize() / 2);
if (m_focusIndex == i)
{
menuImage->setNormalImage(Sprite::create("general/img/dailog_ok_select.png"));
//menuImage->setScale(1.1f);
}
else
{
menuImage->setNormalImage(Sprite::create("general/img/dialog_ok_normal.png"));
//menuImage->setScale(1.0f);
}
menuImage->addChild(lbFont);
}
vct.clear();
}
}
void PopupLayer::keyLeftEvent()
{
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
int buttonMax = menuItem->getChildrenCount();
m_focusIndex -= 1;
if (m_focusIndex < 0)
{
m_focusIndex = buttonMax - 1;
}
setHighLight();
}
}
void PopupLayer::keyRightEvent()
{
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
int buttonMax = menuItem->getChildrenCount();
m_focusIndex += 1;
if (m_focusIndex >= buttonMax)
{
m_focusIndex = 0;
}
setHighLight();
}
}
void PopupLayer::keyEnterEvent()
{
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
Vector<Node *> vct;
vct.pushBack(menuItem->getChildren());
for (int i = 0; i < vct.size(); i++)
{
MenuItemImage *menuImage = (MenuItemImage *)vct.at(i);
if (m_focusIndex == i)
{
PopupLayer::buttonCallBack(menuImage);
return;
}
}
vct.clear();
}
}
void PopupLayer::destroyFromParent()
{
//恢复下层点击按键手柄等事件
getScheduler()->performFunctionInCocosThread([&]() {
Node * parent = this->getParent();
this->removeFromParent();
Director::getInstance()->getEventDispatcher()->resumeEventListenersForTarget(parent, true);
});
}
//全部参数设定好后,在运行时动态加载
void PopupLayer::onEnter()
{
Layer::onEnter();
Size visibleSize = Director::getInstance()->getVisibleSize();
Vec2 center = Vec2(visibleSize.width / 2, visibleSize.height / 2);
Size backGroundSize;
//背景
if (this->getContentSize().equals(Size::ZERO))//传入参数大小为0时
{
Sprite *sp = this->getSpriteBackGround();
sp->setPosition(center);
this->addChild(sp);
backGroundSize = sp->getTexture()->getContentSize();
}
else
{
ui::Scale9Sprite *backGround = this->getSprite9BackGround();
backGround->setContentSize(this->getContentSize());
backGround->setPosition(center);
backGroundSize = this->getContentSize();
this->addChild(backGround);
}
//标题
Label *lbTitle = this->getLabelTitle();
if (lbTitle)
{
lbTitle->setPosition(center + Vec2(0, backGroundSize.height / 2 - 25.0f));
this->addChild(lbTitle);
}
//内容
Label *lbContentText = this->getLabelContentText();
if (lbContentText)
{
lbContentText->setPosition(center);
lbContentText->setDimensions(backGroundSize.width - m_contentPadding * 2, backGroundSize.height - m_contentPaddingTop);
lbContentText->setHorizontalAlignment(kCCTextAlignmentCenter);
//lbContentText->setHorizontalAlignment(kCCTextAlignmentLeft);
this->addChild(lbContentText);
}
//按钮
Menu *menuItem = this->getMenuButton();
if (menuItem)
{
Vector<Node *> vct;
vct.pushBack(menuItem->getChildren());
float buttonWidth = backGroundSize.width / (menuItem->getChildrenCount() + 1);
for (int i = 0; i < vct.size(); i++)
{
Node *node = (Node *)vct.at(i);
node->setPosition(Vec2(visibleSize.width/2 - backGroundSize.width/2 + buttonWidth *(i+1),
visibleSize.height / 2 - backGroundSize.height / 3));
}
vct.clear();
this->addChild(menuItem);
setHighLight();
}
//弹出效果
Sequence *popupActions = Sequence::create(
ScaleTo::create(0.0, 0.0),
ScaleTo::create(0.06, 1.05),
ScaleTo::create(0.08, 0.95),
ScaleTo::create(0.08, 1.0),
NULL
);
this->runAction(popupActions);
//暂停下层点击按键手柄等事件
_eventDispatcher->pauseEventListenersForTarget(this->getParent(), true);
}
void PopupLayer::onExit()
{
Layer::onExit();
}
调用处
//用法:
定义一个弹出层,传入一张背景图片
//PopupLayer* popup = PopupLayer::create("popupBackGround.png");
ContentSize是可选的设置,可以不设置,如果设置则把它当做9图缩放
//popup->setContentSize(CCSizeMake(800, 560));
//popup->setTitle("Message");
//popup->setContentText("Most people... blunder round this cityMost people blunder round this cityMost people blunder round this cityMost people blunder round this city.", 20, 20, 150);
设置回调函数,回调传回一个CCNode以获取tag判断点击的按钮
这只是作为一种封装实现,如果使用delegate那就能够更灵活的控制参数了
添加按钮,设置图片、文字,tag信息
//popup->addButton("yesNormal.png", "yesSelect.png", "Ok", -500);
//popup->addButton("noNormal.png", "noSelect.png", "Cancel", 1);
//popup->setCallBackFunc(this, callfuncN_selector(HelloWorld::buttonCallBack));
//this->addChild(popup);