以上是效果图,其中我点击上面的框,它会弹出下拉框,然后下拉框刚好覆盖下一个按钮,当我选择boy或者girl的时候,不会响应下面的事件。
实现原理:
1: CCMenu的吞噬点击事件,即点击框时,响应事件,不点击,则不响应。
2: 下拉框为一张精灵,加一个tableview。
模仿CCMenu的方式写这个控件
MyDropdownButton.h
#pragma once #include "cocos2d.h" #include "cocos-ext.h" #include <vector> USING_NS_CC; USING_NS_CC_EXT; using namespace std; class MyDropdownButton : public cocos2d::CCSprite, public cocos2d::extension::CCTableViewDataSource, public cocos2d::extension::CCTableViewDelegate { public: MyDropdownButton(void); ~MyDropdownButton(void); bool init(const char* _filePath); static MyDropdownButton* create(const char* _filePath); virtual void onExit(); virtual void onEnterTransitionDidFinish(); private: bool m_bBoxVisible;//下拉框显示 bool m_bEnable;//是否能够点击 bool m_bBoxClicked;//box是否被点击 std::string m_filePath;//按钮的文件路径 vector<std::string> m_vec_listName;//下拉框中的显示的名字 vector<std::string> m_vec_listValue;//下拉框中显示的名字相对应的值。 CCTableView* m_tableView;//tableview public: void setBox(const char* _filePath);//设置下拉框 void setBoxListName(vector<std::string> _vec_listName);//设置下拉框中的显示的名字 void setBoxListValue(vector<std::string> _vec_listValue);//设置下拉框中显示的名字相对应的值。 void setBoxVisible(bool _bVisible); void setEnabled(bool _bEnabled); bool getBoxVisible(){ return m_bBoxVisible; }; bool isEnabled(){return m_bEnable;}; bool isBoxClicked(){return m_bBoxClicked;}; void setBoxClicked(bool _bBoxClicked){m_bBoxClicked = _bBoxClicked;}; CCRect getBoxRect(); private: //tableview 要实现的函数 virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view) {}; virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view) {} virtual void tableCellTouched(cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell); virtual cocos2d::CCSize tableCellSizeForIndex(cocos2d::extension::CCTableView *table, unsigned int idx); virtual cocos2d::extension::CCTableViewCell* tableCellAtIndex(cocos2d::extension::CCTableView *table, unsigned int idx); virtual unsigned int numberOfCellsInTableView(cocos2d::extension::CCTableView *table); };
#include "MyDropdownButton.h" #define BoxTag 9 #define LabelTag 10 MyDropdownButton::MyDropdownButton(void) { } MyDropdownButton::~MyDropdownButton(void) { } MyDropdownButton* MyDropdownButton::create( const char* _filePath ) { MyDropdownButton *sp = new MyDropdownButton(); if (sp && sp->init(_filePath)) { sp->autorelease(); return sp; } CC_SAFE_DELETE(sp); return NULL; } bool MyDropdownButton::init( const char* _filePath ) { bool bRet = false; do { CC_BREAK_IF(! CCSprite::init()); CCSize size = CCDirector::sharedDirector()->getWinSize(); //初始化数据 m_filePath = _filePath; m_bBoxVisible = false; m_bEnable = true; m_bBoxClicked = false; m_vec_listName.clear(); m_vec_listValue.clear(); //按钮图片 this->initWithFile(_filePath); bRet = true; } while (0); return bRet; } void MyDropdownButton::onEnterTransitionDidFinish() { CCSprite::onEnterTransitionDidFinish(); } void MyDropdownButton::onExit() { CCSprite::onExit(); } void MyDropdownButton::setBox( const char* _filePath ) { CCSize mySize = this->getContentSize(); CCSprite* sBox = (CCSprite*)this->getChildByTag(BoxTag); if (sBox) { sBox->removeFromParent(); sBox = NULL; } sBox = CCSprite::create(_filePath); //下啦框的位置位于按钮的下方。边界重叠 sBox->setPosition(ccp(sBox->getContentSize().width/2,-sBox->getContentSize().height/2)); this->addChild(sBox); sBox->setTag(BoxTag); sBox->setVisible(false); } void MyDropdownButton::setBoxListName( vector<std::string> _vec_listName ) { m_vec_listName = _vec_listName; } void MyDropdownButton::setBoxListValue( vector<std::string> _vec_listValue ) { m_vec_listValue = _vec_listValue; } void MyDropdownButton::setBoxVisible( bool _bVisible ) { m_bBoxVisible = _bVisible; CCSprite* sBox = (CCSprite*)this->getChildByTag(BoxTag); if (sBox) { sBox->setVisible(_bVisible); if (_bVisible)//可见 { m_tableView = CCTableView::create(this, sBox->getContentSize()); m_tableView->setDirection(kCCScrollViewDirectionVertical); m_tableView->setPosition(ccp( 0,0 )); m_tableView->setDelegate(this); m_tableView->setVerticalFillOrder(kCCTableViewFillTopDown); sBox->addChild(m_tableView); m_tableView->setTouchPriority(-128); this->setZOrder(this->getZOrder()+10); }else//不可见 { m_tableView->removeFromParent(); m_tableView = NULL; this->setZOrder(this->getZOrder()-10); } } } void MyDropdownButton::setEnabled( bool _bEnabled ) { m_bEnable = _bEnabled; } unsigned int MyDropdownButton::numberOfCellsInTableView( cocos2d::extension::CCTableView *table ) { return m_vec_listName.size(); } cocos2d::CCSize MyDropdownButton::tableCellSizeForIndex( cocos2d::extension::CCTableView *table, unsigned int idx ) { return this->getContentSize(); } cocos2d::extension::CCTableViewCell* MyDropdownButton::tableCellAtIndex( cocos2d::extension::CCTableView *table, unsigned int idx ) { CCTableViewCell *cell = new CCTableViewCell(); if (!cell) { //CCLog("cell in not null---%d",idx); cell = new CCTableViewCell(); cell->autorelease(); } else { CCSize mySize = this->getContentSize(); CCLabelTTF* label = CCLabelTTF::create(m_vec_listName[idx].c_str(),"Arial",30); label->setPosition(ccp(mySize.width/2,mySize.height/2)); cell->addChild(label); label->setColor(ccBLACK); } return cell; } void MyDropdownButton::tableCellTouched( cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell ) { CCSize mySize = this->getContentSize(); CCLabelTTF* label = (CCLabelTTF*)getChildByTag(LabelTag); if (label) { label->removeFromParent(); label = NULL; } label = CCLabelTTF::create(m_vec_listName[cell->getIdx()].c_str(),"Arial",30); label->setPosition(ccp(mySize.width/2,mySize.height/2)); this->addChild(label); label->setColor(ccBLACK); label->setTag(LabelTag); setBoxVisible(false); } cocos2d::CCRect MyDropdownButton::getBoxRect() { CCSprite* sBox = (CCSprite*)this->getChildByTag(BoxTag); if (sBox) { return sBox->boundingBox(); } return CCRectZero; }
#pragma once #include "cocos2d.h" #include "MyDropdownButton.h" USING_NS_CC; class MyDropdownMenu : public cocos2d::CCLayer { public: MyDropdownMenu(void); ~MyDropdownMenu(void); bool initWithArray(CCArray* pArrayOfBtns); static MyDropdownMenu* create(MyDropdownButton* _dropDownBtn, ...); static MyDropdownMenu* createWithBtns(MyDropdownButton *firstBtn, va_list args); static MyDropdownMenu* createWithArray(CCArray* pArrayOfBtns); virtual void onExit(); virtual void registerWithTouchDispatcher(void); virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent); private: MyDropdownButton* itemForTouch(CCTouch *touch); };
#include "MyDropdownMenu.h" MyDropdownMenu::MyDropdownMenu(void) { } MyDropdownMenu::~MyDropdownMenu(void) { } MyDropdownMenu* MyDropdownMenu::create( MyDropdownButton* _dropDownBtn, ... ) { va_list args; va_start(args,_dropDownBtn); MyDropdownMenu *pRet = MyDropdownMenu::createWithBtns(_dropDownBtn, args); va_end(args); return pRet; } MyDropdownMenu* MyDropdownMenu::createWithBtns( MyDropdownButton *firstBtn, va_list args ) { CCArray* pArray = NULL; if( firstBtn ) { pArray = CCArray::create(firstBtn, NULL); MyDropdownButton *i = va_arg(args, MyDropdownButton*); while(i) { pArray->addObject(i); i = va_arg(args, MyDropdownButton*); } } return MyDropdownMenu::createWithArray(pArray); } MyDropdownMenu* MyDropdownMenu::createWithArray( CCArray* pArrayOfBtns ) { MyDropdownMenu *pRet = new MyDropdownMenu(); if (pRet && pRet->initWithArray(pArrayOfBtns)) { pRet->autorelease(); } else { CC_SAFE_DELETE(pRet); } return pRet; } bool MyDropdownMenu::initWithArray( CCArray* pArrayOfBtns ) { if (!CCLayer::init()) { return false; } if (pArrayOfBtns != NULL) { int z=0; CCObject* pObj = NULL; CCARRAY_FOREACH(pArrayOfBtns, pObj) { MyDropdownButton* item = (MyDropdownButton*)pObj; this->addChild(item,z); z++; } } this->setTouchEnabled(true); return true; } void MyDropdownMenu::onExit() { CCLayer::onExit(); } void MyDropdownMenu::registerWithTouchDispatcher( void ) { CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,-128,true); } bool MyDropdownMenu::ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent ) { CCPoint touchPoint = pTouch->getLocation(); MyDropdownButton* btn = itemForTouch(pTouch); if (btn) { if (btn->getBoxVisible()) { if (btn->isBoxClicked()) { return true; } btn->setBoxVisible(false); return true; } btn->setBoxVisible(true); return true; } return false; } MyDropdownButton* MyDropdownMenu::itemForTouch( CCTouch *touch ) { CCPoint touchLocation = touch->getLocation(); if (m_pChildren && m_pChildren->count() > 0) { CCObject* pObject = NULL; //先找出有下拉框的 CCARRAY_FOREACH(m_pChildren, pObject) { MyDropdownButton* pChild = dynamic_cast<MyDropdownButton*>(pObject); if (pChild && pChild->isVisible() && pChild->isEnabled()) { CCPoint local = pChild->convertToNodeSpace(touchLocation); CCSize childSize = pChild->getContentSize(); CCRect r = CCRectMake(0,0,childSize.width,childSize.height); if (pChild->getBoxVisible() == true) { if (pChild->getBoxRect().containsPoint(local)) { pChild->setBoxClicked(true); return pChild; } if (r.containsPoint(local)) { pChild->setBoxClicked(false); return pChild; } continue; } } } //在找出点击按钮的 CCARRAY_FOREACH(m_pChildren, pObject) { MyDropdownButton* pChild = dynamic_cast<MyDropdownButton*>(pObject); if (pChild && pChild->isVisible() && pChild->isEnabled()) { CCPoint local = pChild->convertToNodeSpace(touchLocation); CCSize childSize = pChild->getContentSize(); CCRect r = CCRectMake(0,0,childSize.width,childSize.height); if (pChild->getBoxVisible() == false) { if (r.containsPoint(local)) { pChild->setBoxClicked(false); return pChild; } continue; } } } } return NULL; }
vector<std::string> vec_name; vector<std::string> vec_value; vec_name.push_back("boy"); vec_name.push_back("girl"); vec_value.push_back("0"); vec_value.push_back("1"); MyDropdownButton* btn2 = MyDropdownButton::create("text2.png"); btn2->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2)); btn2->setBox("boxSex.png"); btn2->setBoxListName(vec_name); btn2->setBoxListValue(vec_value); btn2->setScale(0.5f); //btn2->setZOrder(1); MyDropdownButton* btn1 = MyDropdownButton::create("text2.png"); btn1->setPosition(ccp(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2+50)); btn1->setBox("boxSex.png"); btn1->setBoxListName(vec_name); btn1->setBoxListValue(vec_value); btn1->setScale(0.5f); //btn1->setZOrder(2); MyDropdownMenu* dropDownMenu = MyDropdownMenu::create(btn1,btn2,NULL); this->addChild(dropDownMenu);