Cocos2d-x 弹出对话框的设计与实现

咱们时常须要这么些功能,弹出一个层,给与用户一些提示,这也是一种模态窗口,在没有对当前对话框进行确认的时候,不能继续往下操做。node

功能分析

 

咱们设计一个对话框,对话框上有几个按钮(个数可定制),固然有个标题,会让别人一眼看出它之功用,里面能够有些详细的提示文字,须要是模态窗口,并且窗口的大小可变,这样可以更好的适应不一样的屏幕的大小。固然还有一个重要的功能,弹出效果 ~ 虽然从技术角度来讲,实现起来并不难,或者说很是简单,但这会以一个很好的用户体验展现给用户。iphone

代码

1.弹出框类函数

PopupLayer.h测试

 1 //
 2 // PopupLayer.h  3 // PopupDemo  4 //
 5 // Created by IDEA-MAC03 on 13-10-10.  6 //
 7 //  8 
 9 #ifndef __PopupDemo__PopupLayer__ 10 #define __PopupDemo__PopupLayer__
11 
12 #include "cocos2d.h"
13 #include "cocos-ext.h"
14 using namespace cocos2d; 15 using namespace cocos2d::extension; 16 using namespace std; 17 
18 
19 
20 class PopupLayer:public CCLayer 21 { 22   
23 public: 24  PopupLayer(); 25     ~PopupLayer(); 26     
27     virtual bool init(); 28  CREATE_FUNC(PopupLayer); 29     
30      // 须要重写触摸注册函数,从新给定触摸级别
31     virtual void registerWithTouchDispatcher(void); 32      // 重写触摸函数,永远返回 true ,屏蔽其它层,达到 “模态” 效果
33     bool ccTouchBegan(cocos2d::CCTouch *pTouch,cocos2d::CCEvent *pEvent); 34     // 构架,并设置对话框背景图片
35     static PopupLayer* create(const char* backgroundImage); 36     
37      // 它能够显示标题,而且设定显示文字大小
38     void setTitle(const char*title,int fontsize = 20); 39     // 文本内容,padding 为文字到对话框两边预留的距离,这是可控的,距上方的距离亦是如此
40     void setContentText(const char *text, int fontsize = 20, int padding = 50, int paddintTop = 100); 41     // 回调函数,当点击按钮后,咱们关闭弹出层的同事,须要一个回调函数,以通知咱们点击了哪一个按钮(若是有多个)
42     void setCallbackFunc(CCObject* target, SEL_CallFuncN callfun); 43      // 为了添加按钮方面,封装了一个函数,传入些必要的参数
44     bool addButton(const char* normalImage, const char* selectedImage, const char* title, int tag = 0); 45     
46     // 为了在显示层时以前的属性生效,选择在 onEnter 里动态展现
47     virtual void onEnter(); 48     virtual void onExit(); 49     
50 private: 51     
52     void buttonCallback(CCObject* pSender); 53     
54     // 文字内容两边的空白区
55     int m_contentPadding; 56     int m_contentPaddingTop; 57     
58     CCObject* m_callbackListener; 59  SEL_CallFuncN m_callback; 60     
61     CC_SYNTHESIZE_RETAIN(CCMenu*, m__pMenu, MenuButton); 62     CC_SYNTHESIZE_RETAIN(CCSprite*, m__sfBackGround, SpriteBackGround); 63     CC_SYNTHESIZE_RETAIN(CCScale9Sprite*, m__s9BackGround, Sprite9BackGround); 64     CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltTitle, LabelTitle); 65     CC_SYNTHESIZE_RETAIN(CCLabelTTF*, m__ltContentText, LabelContentText); 66 
67 }; 68 
69 
70 
71 
72 #endif /* defined(__PopupDemo__PopupLayer__) */

PopupLayer.cppthis

 1 //
 2 // PopupLayer.cpp  3 // PopupDemo  4 //
 5 // Created by IDEA-MAC03 on 13-10-10.  6 //
 7 //  8 
 9 #include "PopupLayer.h"
 10 
 11 
 12 
 13 PopupLayer::PopupLayer():  14 m__pMenu(NULL)  15 ,m_contentPadding(0)  16 ,m_contentPaddingTop(0)  17 ,m_callbackListener(NULL)  18 ,m_callback(NULL)  19 ,m__sfBackGround(NULL)  20 ,m__s9BackGround(NULL)  21 ,m__ltContentText(NULL)  22 ,m__ltTitle(NULL)  23 {  24     
 25 }  26 
 27 PopupLayer::~PopupLayer()  28 {  29  CC_SAFE_RELEASE(m__pMenu);  30  CC_SAFE_RELEASE(m__sfBackGround);  31  CC_SAFE_RELEASE(m__ltContentText);  32  CC_SAFE_RELEASE(m__ltTitle);  33  CC_SAFE_RELEASE(m__s9BackGround);  34 }  35 
 36 bool PopupLayer::init()  37 {  38     bool bRef = false;  39     do
 40  {  41         CC_BREAK_IF(!CCLayer::init());  42         this->setContentSize(CCSizeZero);  43         // 初始化须要的 Menu
 44         CCMenu* menu = CCMenu::create();  45         menu->setPosition(CCPointZero);  46  setMenuButton(menu);  47         setTouchEnabled(true);  48         bRef = true;  49     } while (0);  50     return bRef;  51 }  52 
 53 
 54 void PopupLayer::registerWithTouchDispatcher()  55 {  56        // 这里的触摸优先级设置为 -128 这保证了,屏蔽下方的触摸
 57     CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -128, true);  58 }  59 
 60 bool PopupLayer::ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent)  61 {  62     CCLog("PopupLayer touch");  63     return true;  64 }  65 
 66 
 67 PopupLayer* PopupLayer::create(const char *backgroundImage)  68 {  69     PopupLayer* ml = PopupLayer::create();  70     ml->setSpriteBackGround(CCSprite::create(backgroundImage));  71     ml->setSprite9BackGround(CCScale9Sprite::create(backgroundImage));  72     return ml;  73 }  74 
 75 
 76 void PopupLayer::setTitle(const char*title,int fontsize)  77 {  78     CCLabelTTF* ltfTitle = CCLabelTTF::create(title, "", fontsize);  79  setLabelTitle(ltfTitle);  80 }  81 
 82 void PopupLayer::setContentText(const char *text, int fontsize, int padding, int paddingTop){  83     CCLabelTTF* ltf = CCLabelTTF::create(text, "", fontsize);  84  setLabelContentText(ltf);  85     m_contentPadding = padding;  86     m_contentPaddingTop = paddingTop;  87 }  88 
 89 void PopupLayer::setCallbackFunc(cocos2d::CCObject *target, SEL_CallFuncN callfun)  90 {  91     m_callbackListener = target;  92     m_callback = callfun;  93 }  94 
 95 
 96 bool PopupLayer::addButton(const char *normalImage, const char *selectedImage, const char *title, int tag){  97     CCSize winSize = CCDirector::sharedDirector()->getWinSize();  98     CCPoint pCenter = ccp(winSize.width / 2, winSize.height / 2);  99     
100     // 建立图片菜单按钮
101     CCMenuItemImage* menuImage = CCMenuItemImage::create(normalImage, selectedImage, this, menu_selector(PopupLayer::buttonCallback)); 102     menuImage->setTag(tag); 103     menuImage->setPosition(pCenter); 104     
105     // 添加文字说明并设置位置
106     CCSize imenu = menuImage->getContentSize(); 107     CCLabelTTF* ttf = CCLabelTTF::create(title, "", 20); 108     ttf->setColor(ccc3(0, 0, 0)); 109     ttf->setPosition(ccp(imenu.width / 2, imenu.height / 2)); 110     menuImage->addChild(ttf); 111     
112     getMenuButton()->addChild(menuImage); 113     return true; 114 } 115 
116 
117 void PopupLayer::buttonCallback(cocos2d::CCObject *pSender){ 118     CCNode* node = dynamic_cast<CCNode*>(pSender); 119     CCLog("touch tag: %d", node->getTag()); 120     if (m_callback && m_callbackListener){ 121         (m_callbackListener->*m_callback)(node); 122  } 123     this->removeFromParentAndCleanup(true); 124 } 125 
126 
127 
128 void PopupLayer::onEnter() 129 { 130  CCLayer::onEnter(); 131     
132     CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 133     CCPoint pCenter = ccp(winSize.width / 2, winSize.height / 2); 134     
135  CCSize contentSize; 136      // 设定好参数,在运行时加载
137     if (getContentSize().equals(CCSizeZero)) 138  { 139         getSpriteBackGround()->setPosition(ccp(winSize.width / 2, winSize.height / 2)); 140         this->addChild(getSpriteBackGround(),0,0); 141         contentSize = getSpriteBackGround()->getTexture()->getContentSize(); 142     }else
143  { 144         CCScale9Sprite *background = getSprite9BackGround(); 145         background->setContentSize(getContentSize()); 146         background->setPosition(ccp(winSize.width / 2, winSize.height / 2)); 147         this->addChild(background,0); 148         contentSize = getContentSize(); 149  } 150     
151     
152      // 添加按钮,并设置其位置
153     this->addChild(getMenuButton()); 154     float btnWidth = contentSize.width/(getMenuButton()->getChildrenCount()+1); 155     
156     CCArray* array = getMenuButton()->getChildren(); 157     CCObject* pObj = NULL; 158     int i = 0; 159  CCARRAY_FOREACH(array, pObj) 160  { 161         CCNode* node = dynamic_cast<CCNode*>(pObj); 162         node->setPosition(ccp(winSize.width / 2 - contentSize.width / 2 + btnWidth * (i + 1), winSize.height / 2 - contentSize.height / 3)); 163         i++; 164  } 165     
166     // 显示对话框标题
167     if (getLabelTitle()) 168  { 169         getLabelTitle()->setPosition(ccpAdd(pCenter, ccp(0, contentSize.height / 2 - 35.0f))); 170         this->addChild(getLabelTitle()); 171  } 172     
173     // 显示文本内容
174     if (getLabelContentText()) 175  { 176         CCLabelTTF* ltf = getLabelContentText(); 177         ltf->setPosition(ccp(winSize.width / 2, winSize.height / 2)); 178           ltf->setDimensions(CCSizeMake(contentSize.width - m_contentPadding * 2, contentSize.height - m_contentPaddingTop)); 179          ltf->setHorizontalAlignment(kCCTextAlignmentLeft); 180         this->addChild(ltf); 181  } 182     
183     CCAction* popupLayer = CCSequence::create(CCScaleTo::create(0.0, 0.0), 184                                               CCScaleTo::create(0.06, 1.05), 185                                               CCScaleTo::create(0.08, 0.95), 186                                               CCScaleTo::create(0.08, 1.0), NULL); 187     this->runAction(popupLayer); 188     
189 } 190 
191 
192 void PopupLayer::onExit() 193 { 194     CCLog("popup on exit."); 195  CCLayer::onExit(); 196 }

2.测试代码spa

 

HelloWorldScene.h.net

 1 #ifndef __HELLOWORLD_SCENE_H__  2 #define __HELLOWORLD_SCENE_H__
 3 
 4 #include "cocos2d.h"
 5 
 6 class HelloWorld : public cocos2d::CCLayer  7 {  8 public:  9     // Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
10     virtual bool init(); 11 
12     // there's no 'id' in cpp, so we recommend to return the class instance pointer
13     static cocos2d::CCScene* scene(); 14     
15     // a selector callback
16     void menuCloseCallback(CCObject* pSender); 17 
18     // preprocessor macro for "static create()" constructor ( node() deprecated )
19  CREATE_FUNC(HelloWorld); 20     
21     void menuCallback(cocos2d::CCObject *pSender); 22     void popupLayer(); 23     void buttonCallback(cocos2d::CCNode *pNode); 24 }; 25 
26 #endif // __HELLOWORLD_SCENE_H__

HelloWorldScene.cpp设计

 1 #include "HelloWorldScene.h"
 2 #include "SimpleAudioEngine.h"
 3 #include "PopupLayer.h"
 4 
 5 using namespace cocos2d;  6 using namespace CocosDenshion;  7 
 8 CCScene* HelloWorld::scene()  9 { 10     // 'scene' is an autorelease object
11     CCScene *scene = CCScene::create(); 12     
13     // 'layer' is an autorelease object
14     HelloWorld *layer = HelloWorld::create(); 15 
16     // add layer as a child to scene
17     scene->addChild(layer); 18 
19     // return the scene
20     return scene; 21 } 22 
23 // on "init" you need to initialize your instance
24 bool HelloWorld::init() 25 { 26     ////////////////////////////// 27     // 1. super init first
28     if ( !CCLayer::init() ) 29  { 30         return false; 31  } 32 
33     CCSize winSize = CCDirector::sharedDirector()->getWinSize(); 34     CCPoint pointCenter = ccp(winSize.width / 2, winSize.height / 2); 35     
36     // 添加背景图片
37     CCSprite* background = CCSprite::create("HelloWorld.png"); 38     background->setPosition(pointCenter); 39     background->setScale(1.5f); 40     this->addChild(background); 41     
42      // 添加菜单
43     CCMenu* menu = CCMenu::create(); 44     
45     CCMenuItemFont* menuItem = CCMenuItemFont::create("popup", this, menu_selector(HelloWorld::menuCallback)); 46     menuItem->setPosition(ccp(winSize.width / 2, winSize.height / 2)); 47     menuItem->setColor(ccc3(0, 0, 0)); 48     menu->addChild(menuItem); 49     
50     
51     menu->setPosition(CCPointZero); 52     this->addChild(menu); 53     
54     
55     
56     return true; 57 } 58 
59 
60 void HelloWorld::menuCallback(cocos2d::CCObject *pSender){ 61  popupLayer(); 62 } 63 
64 void HelloWorld::popupLayer() 65 { 66     // 定义一个弹出层,传入一张背景图
67     PopupLayer* pl = PopupLayer::create("useDialogBox0u00001.png"); 68     // ContentSize 是可选的设置,能够不设置,若是设置把它看成 9 图缩放
69     pl->setContentSize(CCSizeMake(400, 360)); 70     pl->setTitle("吾名一叶"); 71     pl->setContentText("娇兰傲梅世人赏,却少幽芬暗里藏。不看百花共争艳,独爱疏樱一枝香。", 20, 50, 150); 72     // 设置回调函数,回调传回一个 CCNode 以获取 tag 判断点击的按钮 73     // 这只是做为一种封装实现,若是使用 delegate 那就可以更灵活的控制参数了
74     pl->setCallbackFunc(this, callfuncN_selector(HelloWorld::buttonCallback)); 75     // 添加按钮,设置图片,文字,tag 信息
76     pl->addButton("shopBtn0s01.png", "shopBtn0s02.png", "肯定", 0); 77     pl->addButton("bagButton0b1.png", "bagButton0b2.png", "取消", 1); 78     // 添加到当前层
79     this->addChild(pl); 80 } 81 
82 
83 
84 void HelloWorld::buttonCallback(cocos2d::CCNode *pNode){ 85     CCLog("button call back. tag: %d", pNode->getTag()); 86 } 87 
88 void HelloWorld::menuCloseCallback(CCObject* pSender) 89 { 90     CCDirector::sharedDirector()->end(); 91 
92 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
93     exit(0); 94 #endif
95 }

效果图

如上,完成了对话框的基本模型,它实现了如下功能:code

 

  • 一个能够弹出的对话框实现
  • 模态窗口的实现(须要逻辑的控制)
  • 多按钮的支持,位置自适应,提供回调函数
  • 提供标题和内容设置
  • 支持 九图 ,控制适应弹出框大小

 

    固然还有许多其它并无照顾到的功能,或者不完善的地方,这就须要用户本身扩展,定制了,如,这样一个层,至少应该是单例的,任什么时候候只应该存在一个,能够用单例模式实现,对于弹出层的内容方面,这里只有标题和内容,而且标题位置固定,按钮的位置还能够更灵活的设置等。orm

 

注:

在设置按钮位置的时候有可能出现按钮位置不对,特调整以下:

 1 CCMenuItemImage* itemImage = dynamic_case<CCMenuItemImage*>(array->objectAtIndex(0));  2 int count = getMenuButton()->getChildrenCount();  3 int btnWidth = itemImage->getContentSize().width;  4 int padingWidth = (contentSize.width - btnWidth * count) / (count + 1);  5 CCARRAY_FOREACH(array, obj)  6 {  7     CCNode* node = dynamic_cast<CCNode*>(obj);  8     node->setAnchorPoint(ccp(0, 0.5f));  9     node->setPosition(ccp(visibSize.width * 0.5f - contentSize.width * 0.5f + padingWidth * (i + 1) + btnWidth * i, visibSize.height * 0.5f - contentSize.height / 3)); 10      i++          
11 }

 

 

原文连接:http://blog.csdn.net/rexuefengye/article/details/12610909

相关文章
相关标签/搜索