zoukankan      html  css  js  c++  java
  • Cocos2d-x 弹出对话框的设计与实现

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

    功能分析

     

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

    代码

    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.cpp

      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.测试代码

     

    HelloWorldScene.h

     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 }

    效果图

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

     

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

     

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

     

    注:

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

     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

  • 相关阅读:
    linux将命令添加到PATH中
    查看linux服务器时间
    spring参数校验及全局异常处理
    Https协议的工作过程
    反爬虫方式
    telnet进入某个端口后无法退出
    索引操作
    redis output buffer 设置太小导致oom
    mysql查询课程浏览记录表中最近一周浏览次数最多的课程
    C++ 读写注册表
  • 原文地址:https://www.cnblogs.com/atong/p/3365452.html
Copyright © 2011-2022 走看看