zoukankan      html  css  js  c++  java
  • cocos2dx 2.0.4 封装组合框 ComboBox

    cocos2d-x 2.0.4尚未包含组合框组件,在很多需要选择时间、道具等应用场合非常不方便,故而自己封装了一个。基本上跟android标准组件的组合框功能和体验都一模一样了,而且功能更加强大, 完全可以自定义组合框的按钮图片,字体大小,背景图片,按钮高亮图片,以及选择列表的背景等。大小可根据设置的字体大小随意收缩,非常方便。

    先说说使用方法:

    在CCLayer中要使用这个组合框,简单的代码如下:

        ComboBox* comboBox = ComboBox::create("1985", "control/buttonBackground.png", "control/cbobtn_normal.png", "control/cbobtn_hightlight.png", "control/cellbackground.png",  60, 3);
            comboBox->setComboBoxDataFromContinuousInt(1900,2100); // 设置内容为1900-2100的所有数字,需要设置字符串之类的可以参考其他设置内容的接口
            comboBox->setPosition(winSize.width/2, winSize.height/2);
            addChild(comboBox);

    create()函数说明:

    ComboBox::create(const char* text, const char* bgImg, const char* btnImg, const char* hightLightBtnImg, const char* cellBackGround, int fontSize, float borderPix, const char* font="Marker Felt");

    text => 默认显示的文本内容

    bgImg=> 组合框背景图片

    btnImg=>组合框右边按钮普通状态下的图片

    hightLightBtnImg =>组合框右边按钮按下状态下的图片

    cellBackGround => 选择列表单元格的背景图片

    fontSize => 字体大小,决定组合框的大小

    borderPix => 图片边界尺寸,因为图片需要随着组合框缩放,故需要边界尺寸,这个具体可以看看CCScale9Sprite的原理,相当于rectInsets的内容

    font => 字体样式

    附上截图:

    组合框样子:                                                                                        点击按钮弹出选择列表

         

    附上源代码:

    注意,源代码中,MyTableView的实现在我的另外一篇文章中,主要就是修复了CCTableView中不能点击的bug,文章见这里:cocos2d-x 2.0.4 CCTableView 点击无响应问题.

    ComboBox.h

    #ifndef __COMBOBOX_H__
    #define __COMBOBOX_H__
    
    #include "cocos2d.h"
    #include "cocos-ext.h"
    #include "MyTableView.h"
    #include <vector>
    
    USING_NS_CC;
    USING_NS_CC_EXT;
    
    
    typedef std::vector<std::string> ComboBoxDataList;
    
    class ComboBoxTableViewLayer;
    
    class ComboBox : public CCLayer
    {
    public:
        ComboBox();
        virtual ~ComboBox();
        bool init(const char* text, const char* bgImg, const char* btnImg, const char* hightLightBtnImg, const char* cellBackGround, int fontSize, float borderPix, const char* font);
        static ComboBox* create(const char* text, const char* bgImg, const char* btnImg, const char* hightLightBtnImg, const char* cellBackGround, int fontSize, float borderPix, const char* font="Marker Felt");
    
        bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); 
        void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
        void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
        void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    
        void touchUpInside(CCObject* pSender, CCControlEvent event);
    
        void setComboBoxDataList(const ComboBoxDataList& dataList) ;
        void setComboBoxDataFromContinuousInt(int start, int end, int step=1);
        void setComboBoxDataFromContinuousFloat(float start, float end, float step=1.0);
        void clearDataList();
    
        const char* getLabel();
        void setLabel(const char* label);
    
    protected:
        void setContentSize(const CCSize& s);
    
    protected:
        CCLabelTTF* m_label;
        CCControlButton* m_button;
        CCScale9Sprite* m_backGround;
        ComboBoxTableViewLayer* m_tableViewLayer;
        ComboBoxDataList m_dataList;
    
        const char* m_cellBackGround;
        const char* m_font;
        float m_borderPix;
        float m_fontSize;
    };
    
    
    class ComboBoxTableViewLayer : public CCLayer, public CCTableViewDataSource, public CCTableViewDelegate
    {
    public:
        ComboBoxTableViewLayer();
        ~ComboBoxTableViewLayer();
    
        virtual bool init(ComboBoxDataList* dataList, const char* cellBackGround, float borderPix, float fontSize, const char* font);  
    
        static ComboBoxTableViewLayer* create(ComboBox* frame, ComboBoxDataList* dataList, const char* cellBackGround, float borderPix, float fontSize, const char* font);
    
        void reloadDataList();
        MyTableView* getTableView() { return m_tableView; }
        
        virtual void scrollViewDidScroll(CCScrollView* view) {};
        virtual void scrollViewDidZoom(CCScrollView* view) {}
        virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell);
        virtual CCSize cellSizeForTable(CCTableView *table);
        virtual CCTableViewCell* tableCellAtIndex(CCTableView *table, unsigned int idx);
        virtual unsigned int numberOfCellsInTableView(CCTableView *table);
        void setFrame(ComboBox* frame) { m_frame = frame;}
    
        bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);
        void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);
        void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);
        void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);
    
    
    
        void onEnter();
        void onExit();
    
    
    protected:
        const char* m_cellBackGround;
        float m_borderPix;
        float m_fontSize;
        const char* m_font;
        CCRect m_backGroundRect;
        CCRect m_backGroundRectInsets;
        ComboBoxDataList* m_dataList;
        MyTableView* m_tableView;
        ComboBox* m_frame;
    
    };
    
    
    
    #endif

    ComboBox.cpp:

    #include "ComboBox.h"
    
    ComboBox::ComboBox()
        :m_label(NULL), m_button(NULL), m_backGround(NULL), m_tableViewLayer(NULL)
    {
    }
    
    ComboBox::~ComboBox()
    {
        if (m_label) {
            m_label->release();
        }
        if (m_button) {
            m_button->release();
        }
        if (m_backGround) {
            m_backGround->release();
        }
    
        if (m_tableViewLayer) {
            m_tableViewLayer->release();
        }
    }
    
    ComboBox* ComboBox::create(const char* text, const char* bgImg, const char* btnImg, const char* hightLightBtnImg, const char* cellBackGround, int fontSize, float border, const char* font )
    {
        ComboBox* comboBox = new ComboBox();
        if (comboBox && comboBox->init(text, bgImg, btnImg, hightLightBtnImg, cellBackGround, fontSize, border, font)) {
            comboBox->autorelease();
            return comboBox;
        } else {
            delete comboBox;
            return NULL;
        }
    }
    
    const char* ComboBox::getLabel()
    {
        return m_label->getString();
    }
    
    void ComboBox::setLabel(const char* label) 
    {
        m_label->setString(label);
    }
    
    bool ComboBox::init(const char* text, const char* bgImg, const char* btnImg, const char* hightLightBtnImg, const char* cellBackGround, int fontSize, float borderPix,  const char* font) 
    {
        m_cellBackGround = cellBackGround;
        m_borderPix = borderPix;
        m_fontSize = (float)fontSize;
        m_font = font;
    
        if (!CCLayer::init()) {
            return false;
        }
    
        // 支持AnchorPoint定位, 默认情况下Layer不支持
        ignoreAnchorPointForPosition(false);
    
        // 支持触屏
        setTouchEnabled(true);
    
        // 创建Label
        CCSize size;
        m_label = CCLabelTTF::create(text, font, fontSize);
        if (!m_label) return false;
        m_label->setPosition(ccp(m_label->getContentSize().width/2, m_label->getContentSize().height/2));
        m_label->retain();
        addChild(m_label, 1);
        size = m_label->getContentSize();
    
        // 创建按钮
        float space = 3;
    
        /// 由于按钮图片可能是大图片,需要收缩,所以采用三个参数的create,需要先获取图片大小
        CCSprite* tsp = CCSprite::create(btnImg);
        CCSize s = tsp->getContentSize();
        CCRect imgRect = CCRectMake(0,0, s.width, s.height);
        CCRect imgRectInsets = CCRectMake(borderPix, borderPix, s.width-2*borderPix, s.height-2*borderPix);
        tsp->release();
    
        CCScale9Sprite *backgroundButton = CCScale9Sprite::create(btnImg, imgRect, imgRectInsets);
        CCScale9Sprite *backgroundHighlightedButton = CCScale9Sprite::create(hightLightBtnImg, imgRect, imgRectInsets);
        m_button = CCControlButton::create(backgroundButton);
        m_button->setZoomOnTouchDown(false);
        m_button->setBackgroundSpriteForState(backgroundHighlightedButton, CCControlStateHighlighted);
        m_button->setPreferredSize(CCSizeMake(size.height, size.height));
        m_button->setPosition(m_label->getContentSize().width + m_button->getContentSize().width/2 + space, m_button->getContentSize().height/2);
        m_button->addTargetWithActionForControlEvents(this, cccontrol_selector(ComboBox::touchUpInside), CCControlEventTouchUpInside);
        m_button->retain();
        addChild(m_button, 1);
        
        size.width += m_button->getContentSize().width + space;
        if (m_button->getContentSize().height > size.height) {
            size.height = m_button->getContentSize().height;
        }
    
        // 创建背景, 背景图片正常都是拉伸,用一个参数的create够了,如果背景还搞大图片,那就不能怪我了。。。
        m_backGround = CCScale9Sprite::create(bgImg);
        m_backGround->setPreferredSize(size);
        m_backGround->setPosition(ccp(m_backGround->getContentSize().width/2, m_backGround->getContentSize().height/2));
        m_backGround->retain();
        addChild(m_backGround, 0);
    
        this->setContentSize(size);
    
        //m_tableViewLayer = ComboBoxTableViewLayer::create(&m_dataList, cellBackGround, borderPix, (float)fontSize, font); 
        //m_tableViewLayer->retain();
    }
    
    void ComboBox::setComboBoxDataList(const ComboBoxDataList& dataList)
    {
        m_dataList = dataList;
    }
    
    void ComboBox::setComboBoxDataFromContinuousInt(int start, int end, int step)
    {
        char buf[50];
        for (int i=start; i <= end; i+=step)
        {
            sprintf(buf, "%d", i);
            m_dataList.push_back(buf);
        }
    }
    void ComboBox::setComboBoxDataFromContinuousFloat(float start, float end, float step)
    {
        char buf[50];
        for (float i=start; i <= end; i+=step)
        {
            sprintf(buf, "%f", i);
            m_dataList.push_back(buf);
        }
    }
    
    void ComboBox::clearDataList()
    {
        m_dataList.clear();
    }
    
    void ComboBox::setContentSize(const CCSize& s)
    {
        CCLayer::setContentSize(s);
    }
    
    
    bool ComboBox::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent) 
    {
        CCPoint p = m_button->getPosition();
        p.x+=1;
        p.y+=1;
        pTouch->setTouchInfo(pTouch->getID(), p.x, p.y);
        m_button->ccTouchBegan(pTouch, pEvent);
        return true;    // 屏蔽该消息不往下传递
    }
    
    void ComboBox::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent) 
    {
        CCPoint p = m_button->getPosition();
        p.x+=1;
        p.y+=1;
        pTouch->setTouchInfo(pTouch->getID(), p.x, p.y);
        m_button->ccTouchMoved(pTouch, pEvent);
    }
    
    void ComboBox::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent) 
    {
        CCPoint p = m_button->getPosition();
        p.x+=1;
        p.y+=1;
        pTouch->setTouchInfo(pTouch->getID(), p.x, p.y);
        m_button->ccTouchEnded(pTouch, pEvent);
    }
    
    void ComboBox::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent) 
    {
        CCPoint p = m_button->getPosition();
        p.x+=1;
        p.y+=1;
        pTouch->setTouchInfo(pTouch->getID(), p.x, p.y);
        m_button->ccTouchEnded(pTouch, pEvent);
    }
    
    void ComboBox::touchUpInside(CCObject* pSender, CCControlEvent event)
    {
        CCLog("touchUpInside");
        CCSize winSize = CCDirector::sharedDirector()->getWinSize();
        float fontSize = (float)m_fontSize/2;
        if (fontSize < 20) {
            fontSize = 20;
        }
        ComboBoxTableViewLayer* layer = ComboBoxTableViewLayer::create(this, &m_dataList, m_cellBackGround, m_borderPix, fontSize, m_font); 
        layer->setAnchorPoint(ccp(0.5,0.5));
        layer->setPosition(ccp(winSize.width/2, winSize.height/2));
        CCScene* curScene = CCDirector::sharedDirector()->getRunningScene();
        int cnt = curScene->getChildrenCount();
        CCLog("cnt=%d", cnt);
        curScene->addChild(layer, cnt+15);
    }
    
    
    
    
    ComboBoxTableViewLayer::ComboBoxTableViewLayer() 
        :m_tableView(NULL)
    {
    }
    
    ComboBoxTableViewLayer::~ComboBoxTableViewLayer()
    {
        CC_SAFE_RELEASE(m_tableView);
    }
    
    ComboBoxTableViewLayer* ComboBoxTableViewLayer::create(ComboBox* frame, ComboBoxDataList* dataList, const char* cellBackGround, float borderPix, float fontSize, const char* font)
    {
        ComboBoxTableViewLayer* layer = new ComboBoxTableViewLayer();
        if (layer && layer->init(dataList, cellBackGround, borderPix, fontSize, font)) {
            layer->setFrame(frame);
            layer->autorelease();
            return layer;
        }else {
            CC_SAFE_DELETE(layer);
            return NULL;
        }
    }
    
    bool ComboBoxTableViewLayer::init(ComboBoxDataList* dataList, const char* cellBackGround, float borderPix, float fontSize, const char* font)
    {
        m_dataList = dataList;
        m_cellBackGround = cellBackGround;
        m_borderPix = borderPix;
        m_fontSize = fontSize;
        m_font = font;
    
        CCLog("ComboBoxTableViewLayer, cellBackGround=%s, borderPix=%f, fontSize=%f, font=%s", m_cellBackGround, m_borderPix, m_fontSize, m_font);
    
        if ( !CCLayer::init() )
        {
            return false;
        }
    
        /// 支持锚点
        ignoreAnchorPointForPosition(false);
    
        // 先保存图片的大小
        CCSprite* tps = CCSprite::create(cellBackGround);
        CCSize s = tps->getContentSize();
        m_backGroundRect = CCRectMake(0,0, s.width, s.height);
        m_backGroundRectInsets = CCRectMake(m_borderPix, m_borderPix, s.width-2*m_borderPix, s.height-2*m_borderPix);
        tps->release();
    
    
        CCSize winSize = CCDirector::sharedDirector()->getWinSize();
        CCSize contentSize = CCSizeMake(winSize.width*0.9, winSize.height*0.9);
    
        m_tableView = MyTableView::create(this, contentSize);
        m_tableView->setDirection(kCCScrollViewDirectionVertical);
        m_tableView->setDelegate(this);
        m_tableView->setVerticalFillOrder(kCCTableViewFillTopDown);
        m_tableView->reloadData();
        m_tableView->retain();
        this->addChild(m_tableView);
    
        setContentSize(contentSize);
    
        CCSize sx = getContentSize();
        CCLog("cctt.w,h:%f,%f", sx.width, sx.height);
    
        return true;
    }
    
    
    void ComboBoxTableViewLayer::tableCellTouched(CCTableView* table, CCTableViewCell* cell)
    {
        CCLog("cell touched at index: %i", cell->getIdx());
        const char* name = ((CCLabelTTF*)(cell->getChildByTag(123)))->getString();
        m_frame->setLabel(name);
        this->removeFromParentAndCleanup(true);
    }
    
    CCSize ComboBoxTableViewLayer::cellSizeForTable(CCTableView *table)
    {
        CCSize contentSize = getContentSize();
        return CCSizeMake(contentSize.width, m_fontSize+15);
    }
    
    CCTableViewCell* ComboBoxTableViewLayer::tableCellAtIndex(CCTableView *table, unsigned int idx)
    {
        std::string str = (*m_dataList)[idx];
        CCTableViewCell *cell = table->dequeueCell();
    
        if (!cell) {
            CCLog("add str:%s", str.c_str());
            CCSize s = cellSizeForTable(NULL);
            cell = new CCTableViewCell();
            cell->autorelease();
            CCScale9Sprite* backGround = CCScale9Sprite::create(m_cellBackGround, m_backGroundRect, m_backGroundRectInsets); 
            backGround->setContentSize(s);
            backGround->setPosition(CCPointZero);
            backGround->setAnchorPoint(CCPointZero);
            cell->addChild(backGround, 0);
            CCLabelTTF *label = CCLabelTTF::create(str.c_str(), m_font, m_fontSize);
            label->setPosition(CCPointZero);
            label->setAnchorPoint(CCPointZero);
            label->setTag(123);
            cell->addChild(label, 1);
        }
        else
        {
            CCLabelTTF *label = (CCLabelTTF*)cell->getChildByTag(123);
            label->setString(str.c_str());
        }
    
        return cell;
    }
    
    unsigned int ComboBoxTableViewLayer::numberOfCellsInTableView(CCTableView *table)
    {
        return m_dataList->size();
    }
    
    void ComboBoxTableViewLayer::reloadDataList()
    {
        m_tableView->reloadData();
    }
    
    bool ComboBoxTableViewLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
    {
        m_tableView->ccTouchBegan(pTouch, pEvent);
        return true;
    }
    
    void ComboBoxTableViewLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
    {
        m_tableView->ccTouchMoved(pTouch, pEvent);
    }
    
    void ComboBoxTableViewLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
    {
        m_tableView->ccTouchEnded(pTouch, pEvent);
    }
    
    void ComboBoxTableViewLayer::ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent)
    {
        m_tableView->ccTouchEnded(pTouch, pEvent);
    }
    
    
    void ComboBoxTableViewLayer::onEnter()
    {
        CCLayer::onEnter();
        CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, -129, true);
    }
    
    void ComboBoxTableViewLayer::onExit()
    {
        CCLayer::onExit();
        CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
    }
  • 相关阅读:
    uva 11080(二分图染色)
    poj 3255(次短路)
    uva 707(记忆化搜索)
    uva 436(floyd变形)
    uva 11748(求可达矩阵)
    uva 11573(bfs)
    Codeforces Round #226 (Div. 2) 解题报告
    uva 11354(最小瓶颈路--多组询问 MST+LCA倍增)
    uva 534(最小瓶颈路)
    uva 538(简单图论 入度出度)
  • 原文地址:https://www.cnblogs.com/moodlxs/p/2837747.html
Copyright © 2011-2022 走看看