以上是效果图,其中我点击上面的框,它会弹出下拉框,然后下拉框刚好覆盖下一个按钮,当我选择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);
};
MyDropdownButton.cpp
#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;
}
MyDropdownMenu.h
#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);
};
MyDropdownMenu.cpp
#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);
这样就可以实现了,有什么bug可以告诉我哈。