cocos2d-x学习日志(12) --弹出对话框的设计与实现

来源:互联网 发布:locale java 编辑:程序博客网 时间:2024/05/23 13:32

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


功能分析

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

代码

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 instancebool 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

原创粉丝点击