我們時常需要這麼些功能,彈出一個層,給與用戶一些提示,這也是一種模態窗口,在沒有對當前對話框進行確認的時候,不能繼續往下操作。
功能分析
我們設計一個對話框,對話框上有幾個按鈕(個數可定製),當然有個標題,會讓別人一眼看出它之功用,裡面可以有些詳細的提示文字,需要是模態窗口,而且窗口的大小可變,這樣能夠更好的適應不同的屏幕的大小。當然還有一個重要的功能,彈出效果 ~ 雖然從技術角度來說,實現起來並不難,或者說非常簡單,但這會以一個很好的用戶體驗展示給用戶。
代碼
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
沒有留言:
張貼留言