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

相關文章
相關標籤/搜索