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);}
联系客服