cocos2d-x学习日志(12) --弹出对话框的设计与实现
我们时常需要这么些功能,弹出一个层,给与用户一些提示,这也是一种模态窗口,在没有对当前对话框进行确认的时候,不能继续往下操作。
功能分析
我们设计一个对话框,对话框上有几个按钮(个数可定制),当然有个标题,会让别人一眼看出它之功用,里面可以有些详细的提示文字,需要是模态窗口,而且窗口的大小可变,这样能够更好的适应不同的屏幕的大小。当然还有一个重要的功能,弹出效果 ~ 虽然从技术角度来说,实现起来并不难,或者说非常简单,但这会以一个很好的用户体验展示给用户。
代码
1.弹出框类
PopupLayer.h
//
// PopupLayer.h
// PopupDemo
//
// Created by IDEA-MAC03 on 13-10-10.
//
// #ifndef __PopupDemo__PopupLayer__
#define __PopupDemo__PopupLayer__ #include "cocos2d.h"
#include "cocos-ext.h"
using namespace cocos2d;
using namespace cocos2d::extension;
using namespace std; class PopupLayer:public CCLayer
{ public:
PopupLayer();
~PopupLayer(); virtual bool init();
CREATE_FUNC(PopupLayer); // 需要重写触摸注册函数,重新给定触摸级别
virtual void registerWithTouchDispatcher(void);
// 重写触摸函数,永远返回 true ,屏蔽其它层,达到 “模态” 效果
bool ccTouchBegan(cocos2d::CCTouch *pTouch,cocos2d::CCEvent *pEvent);
// 构架,并设置对话框背景图片
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 paddintTop = 100);
// 回调函数,当点击按钮后,我们关闭弹出层的同事,需要一个回调函数,以通知我们点击了哪个按钮(如果有多个)
void setCallbackFunc(CCObject* target, SEL_CallFuncN callfun);
// 为了添加按钮方面,封装了一个函数,传入些必要的参数
bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0); // 为了在显示层时之前的属性生效,选择在 onEnter 里动态展示
virtual void onEnter();
virtual void onExit(); private: void buttonCallback(CCObject* pSender); // 文字内容两边的空白区
int m_contentPadding;
int m_contentPaddingTop; CCObject* m_callbackListener;
SEL_CallFuncN m_callback; CC_SYNTHESIZE_RETAIN(CCMenu*, m__pMenu, MenuButton);
CC_SYNTHESIZE_RETAIN(CCSprite*, m__sfBackGround, SpriteBackGround);
CC_SYNTHESIZE_RETAIN(CCScale9Sprite*, m__s9BackGround, Sprite9BackGround);
CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltTitle, LabelTitle);
CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltContentText, LabelContentText); }; #endif /* defined(__PopupDemo__PopupLayer__) */
PopupLayer.cpp
//
// PopupLayer.cpp
// PopupDemo
//
// Created by IDEA-MAC03 on 13-10-10.
//
// #include "PopupLayer.h" PopupLayer::PopupLayer():
m__pMenu(NULL)
,m_contentPadding(0)
,m_contentPaddingTop(0)
,m_callbackListener(NULL)
,m_callback(NULL)
,m__sfBackGround(NULL)
,m__s9BackGround(NULL)
,m__ltContentText(NULL)
,m__ltTitle(NULL)
{ } PopupLayer::~PopupLayer()
{
CC_SAFE_RELEASE(m__pMenu);
CC_SAFE_RELEASE(m__sfBackGround);
CC_SAFE_RELEASE(m__ltContentText);
CC_SAFE_RELEASE(m__ltTitle);
CC_SAFE_RELEASE(m__s9BackGround);
} bool PopupLayer::init()
{
bool bRef = false;
do
{
CC_BREAK_IF(!CCLayer::init());
this->setContentSize(CCSizeZero);
// 初始化需要的 Menu
CCMenu* menu = CCMenu::create();
menu->setPosition(CCPointZero);
setMenuButton(menu);
setTouchEnabled(true);
bRef = true;
} while (0);
return bRef;
} void PopupLayer::registerWithTouchDispatcher()
{
// 这里的触摸优先级设置为 -128 这保证了,屏蔽下方的触摸
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);
} bool PopupLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)
{
CCLog("PopupLayer touch");
return true;
} PopupLayer* PopupLayer::create(const char *backgroundImage)
{
PopupLayer* ml = PopupLayer::create();
ml->setSpriteBackGround(CCSprite::create(backgroundImage));
ml->setSprite9BackGround(CCScale9Sprite::create(backgroundImage));
return ml;
} void PopupLayer::setTitle(const char*title,int fontsize)
{
CCLabelTTF* ltfTitle = CCLabelTTF::create(title, "", fontsize);
setLabelTitle(ltfTitle);
} void PopupLayer::setContentText(const char *text, int fontsize, int padding, int paddingTop){
CCLabelTTF* ltf = CCLabelTTF::create(text, "", fontsize);
setLabelContentText(ltf);
m_contentPadding = padding;
m_contentPaddingTop = paddingTop;
} void PopupLayer::setCallbackFunc(cocos2d::CCObject *target, SEL_CallFuncN callfun)
{
m_callbackListener = target;
m_callback = callfun;
} bool PopupLayer::addButton(const char *normalImage, const char *selectedImage, const char *title, int tag){
CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCPoint pCenter = ccp(winSize.width / 2, winSize.height / 2); // 创建图片菜单按钮
CCMenuItemImage* menuImage = CCMenuItemImage::create(normalImage, selectedImage, this, menu_selector(PopupLayer::buttonCallback));
menuImage->setTag(tag);
menuImage->setPosition(pCenter); // 添加文字说明并设置位置
CCSize imenu = menuImage->getContentSize();
CCLabelTTF* ttf = CCLabelTTF::create(title, "", 20);
ttf->setColor(ccc3(0, 0, 0));
ttf->setPosition(ccp(imenu.width / 2, imenu.height / 2));
menuImage->addChild(ttf); getMenuButton()->addChild(menuImage);
return true;
} void PopupLayer::buttonCallback(cocos2d::CCObject *pSender){
CCNode* node = dynamic_cast<CCNode*>(pSender);
CCLog("touch tag: %d", node->getTag());
if (m_callback && m_callbackListener){
(m_callbackListener->*m_callback)(node);
}
this->removeFromParentAndCleanup(true);
} void PopupLayer::onEnter()
{
CCLayer::onEnter(); CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCPoint pCenter = ccp(winSize.width / 2, winSize.height / 2); CCSize contentSize;
// 设定好参数,在运行时加载
if (getContentSize().equals(CCSizeZero))
{
getSpriteBackGround()->setPosition(ccp(winSize.width / 2, winSize.height / 2));
this->addChild(getSpriteBackGround(),0,0);
contentSize = getSpriteBackGround()->getTexture()->getContentSize();
}else
{
CCScale9Sprite *background = getSprite9BackGround();
background->setContentSize(getContentSize());
background->setPosition(ccp(winSize.width / 2, winSize.height / 2));
this->addChild(background,0);
contentSize = getContentSize();
} // 添加按钮,并设置其位置
this->addChild(getMenuButton());
float btnWidth = contentSize.width/(getMenuButton()->getChildrenCount()+1); CCArray* array = getMenuButton()->getChildren();
CCObject* pObj = NULL;
int i = 0;
CCARRAY_FOREACH(array, pObj)
{
CCNode* node = dynamic_cast<CCNode*>(pObj);
node->setPosition(ccp(winSize.width / 2 - contentSize.width / 2 + btnWidth * (i + 1), winSize.height / 2 - contentSize.height / 3));
i++;
} // 显示对话框标题
if (getLabelTitle())
{
getLabelTitle()->setPosition(ccpAdd(pCenter, ccp(0, contentSize.height / 2 - 35.0f)));
this->addChild(getLabelTitle());
} // 显示文本内容
if (getLabelContentText())
{
CCLabelTTF* ltf = getLabelContentText();
ltf->setPosition(ccp(winSize.width / 2, winSize.height / 2));
ltf->setDimensions(CCSizeMake(contentSize.width - m_contentPadding * 2, contentSize.height - m_contentPaddingTop));
ltf->setHorizontalAlignment(kCCTextAlignmentLeft);
this->addChild(ltf);
} CCAction* popupLayer = CCSequence::create(CCScaleTo::create(0.0, 0.0),
CCScaleTo::create(0.06, 1.05),
CCScaleTo::create(0.08, 0.95),
CCScaleTo::create(0.08, 1.0), NULL);
this->runAction(popupLayer); } void PopupLayer::onExit()
{
CCLog("popup on exit.");
CCLayer::onExit();
}
2.测试代码
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" class HelloWorld : public cocos2d::CCLayer
{
public:
// Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
virtual bool init(); // there's no 'id' in cpp, so we recommend to return the class instance pointer
static cocos2d::CCScene* scene(); // a selector callback
void menuCloseCallback(CCObject* pSender); // preprocessor macro for "static create()" constructor ( node() deprecated )
CREATE_FUNC(HelloWorld); void menuCallback(cocos2d::CCObject *pSender);
void popupLayer();
void buttonCallback(cocos2d::CCNode *pNode);
}; #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
#include "PopupLayer.h" using namespace cocos2d;
using namespace CocosDenshion; CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create(); // 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create(); // add layer as a child to scene
scene->addChild(layer); // return the scene
return scene;
} // on "init" you need to initialize your instance
bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
} CCSize winSize = CCDirector::sharedDirector()->getWinSize();
CCPoint pointCenter = ccp(winSize.width / 2, winSize.height / 2); // 添加背景图片
CCSprite* background = CCSprite::create("HelloWorld.png");
background->setPosition(pointCenter);
background->setScale(1.5f);
this->addChild(background); // 添加菜单
CCMenu* menu = CCMenu::create(); CCMenuItemFont* menuItem = CCMenuItemFont::create("popup", this, menu_selector(HelloWorld::menuCallback));
menuItem->setPosition(ccp(winSize.width / 2, winSize.height / 2));
menuItem->setColor(ccc3(0, 0, 0));
menu->addChild(menuItem); menu->setPosition(CCPointZero);
this->addChild(menu); return true;
} void HelloWorld::menuCallback(cocos2d::CCObject *pSender){
popupLayer();
} void HelloWorld::popupLayer()
{
// 定义一个弹出层,传入一张背景图
PopupLayer* pl = PopupLayer::create("useDialogBox0u00001.png");
// ContentSize 是可选的设置,可以不设置,如果设置把它当作 9 图缩放
pl->setContentSize(CCSizeMake(400, 360));
pl->setTitle("吾名一叶");
pl->setContentText("娇兰傲梅世人赏,却少幽芬暗里藏。不看百花共争艳,独爱疏樱一枝香。", 20, 50, 150);
// 设置回调函数,回调传回一个 CCNode 以获取 tag 判断点击的按钮
// 这只是作为一种封装实现,如果使用 delegate 那就能够更灵活的控制参数了
pl->setCallbackFunc(this, callfuncN_selector(HelloWorld::buttonCallback));
// 添加按钮,设置图片,文字,tag 信息
pl->addButton("shopBtn0s01.png", "shopBtn0s02.png", "确定", 0);
pl->addButton("bagButton0b1.png", "bagButton0b2.png", "取消", 1);
// 添加到当前层
this->addChild(pl);
} void HelloWorld::buttonCallback(cocos2d::CCNode *pNode){
CCLog("button call back. tag: %d", pNode->getTag());
} void HelloWorld::menuCloseCallback(CCObject* pSender)
{
CCDirector::sharedDirector()->end(); #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
}
效果图
如上,完成了对话框的基本模型,它实现了以下功能:
- 一个可以弹出的对话框实现
- 模态窗口的实现(需要逻辑的控制)
- 多按钮的支持,位置自适应,提供回调函数
- 提供标题和内容设置
- 支持 九图 ,控制适应弹出框大小
当然还有许多其它并没有照顾到的功能,或者不完善的地方,这就需要用户自己扩展,定制了,如,这样一个层,至少应该是单例的,任何时候只应该存在一个,可以用单例模式实现,对于弹出层的内容方面,这里只有标题和内容,并且标题位置固定,按钮的位置还可以更灵活的设置等。
详解文章:http://www.ityran.com/archives/4854
cocos2d-x学习日志(12) --弹出对话框的设计与实现的更多相关文章
- 【转】Cocos2d-x 弹出对话框的设计与实现
转自:http://www.tairan.com/archives/4854 我们时常需要这么些功能,弹出一个层,给与用户一些提示,这也是一种模态窗口,在没有对当前对话框进行确认的时候,不能继续往下操 ...
- jQuery学习笔记——弹出对话框
引用jQuery库文件的<script>标签,必须放在引用自定义脚本文件的<script>标签之前.否则,在编写的代码中将不能引用到jQuery框架 <script ty ...
- Xamarin.Forms弹出对话框插件
微信公众号:Dotnet9,网站:Dotnet9,问题或建议,请网站留言: 如果您觉得Dotnet9对您有帮助,欢迎赞赏. Xamarin.Forms弹出对话框插件 内容目录 实现效果 业务场景 编码 ...
- 安卓弹出对话框——Alertdialog
在Android开发当中,在界面上弹出一个Dialog对话框使我们经常需要做的,本篇随笔将详细的讲解Dialog对话框这个概念,包括定义不同样式的对话框. 一.Dialog 我们首先来看看androi ...
- dos命令弹出对话框---Msg命令详解
标签: dos批处理对话框 2015-11-12 17:20 497人阅读 评论(0) 收藏 举报 脚本(30) 版权声明:本文为博主原创文章,未经博主允许不得转载. dos命令弹出对话框---Ms ...
- 安卓弹出对话框——Alertdialog(一)
首先看各种样式的对话框: 我们看到,Dialog有很多的子类实现,所以我们要定义一个对话框,使用其子类来实例化一个即可,而不要直接使用Dialog这个父类来构造. 二.AlertDialog 今天我们 ...
- JavaScript中的三种弹出对话框
学习过js的小伙伴会发现,我们在一些实例中用到了alert()方法.prompt()方法.prompt()方法,他们都是在屏幕上弹出一个对话框,并且在上面显示括号内的内容,使用这种方法使得页面的交互性 ...
- js弹出对话框的三种方式(转)
原文地址:https://www.jb51.net/article/81376.htm javascript的三种对话框是通过调用window对象的三个方法alert(),confirm()和prom ...
- cocos2dx 3.x(纯代码实现弹出对话框/提示框/警告框)
头文件: // // PopAlertDialog.h // macstudycocos2dx // // Created by WangWei on 15/6/8. // // #ifndef ...
随机推荐
- Love Hotels and Unicode[转]
原文地址:http://www.reigndesign.com/blog/love-hotels-and-unicode/ 讲得挺通俗的一篇文章 On Sunday 28 October I atte ...
- 重写equal要重写 hashCode的原因
public class Test { public static void main(String[] args) { Person person1 = new Person(); person1. ...
- DevExpress中ChartControl柱状图(Bar)用法
我的数据 代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 chartControl1.Series.Clear(); ...
- SecureCRT 绝佳配色方案, 保护你的眼睛(转发)
SecureCRT 绝佳配色方案, 保护你的眼睛 关键词:SecureCRT配色, SecureCRT设置颜色, Linux终端配色,Linux终端颜色设置. 终端有一个好的配色,不仅能保护自己的眼睛 ...
- 2014.12.01 B/S 使用VS建立Web网站
要求:从hr数据库info表读取数据,在Web网站中显示为如图: 用DW绘制一个表格,然后将代码拷贝到新建的网站主页代码中 <div> <table bgcolor=" w ...
- MySQL报错:ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password:NO)
1.关闭mysql # service mysqld stop2.屏蔽权限 # mysqld_safe --skip-grant-table 屏幕出现: Starting demo fro ...
- 加密传输SSL协议3_非对称加密
困死了,这里对非对称加密体系开个头,具体的实验明天写 非对称加密体系 为了解决对称加密中密钥的传输的问题,一些天才的数学家就提出了非对称式的加密体系,也称为公钥加密体系. 加密和解密的密钥是不同的.一 ...
- Linux学习之(())操作符
在刚开始学习inux shell脚本编程时候,对于它的 四则运算以及逻辑运算.估计很多朋友都感觉比较难以接受.特变逻辑运算符”[]”使用时候,必须保证运算符与算数 之间有空格. 四则运算也只能借助:l ...
- Day4_代码重用与函数
知识点速记: 重用代码的方法:脚本包含require().include(); 全局配置文件php.ini(auto_prepend_file/auto_append_file); 目录配置文件.ht ...
- KVO和通知中心
苹果其实在语言层面为我们做了很多事,比如Category实现装饰模式的意图,target-action实现命令模式意图等等,对于观察者模式,苹果也提供了KVO和通知中心,给开发者提供了极大的便利. 观 ...