cocos2d-x 控件: 下拉框,(模仿CCMenu)

  • Post author:
  • Post category:其他



以上是效果图,其中我点击上面的框,它会弹出下拉框,然后下拉框刚好覆盖下一个按钮,当我选择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可以告诉我哈。



版权声明:本文为cwn0812原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。