cocos2d-x tree 控件实现

闲来无聊码码代码 哈哈

使用的是cocos2d-x 3.12

支持无限层,滚动条,可以直接用,可以直接用了,代码在细节上还可以调整调整

上传时TreeNode 头文件有几个没用到的函数,漏删除了,可以自己删除掉  


#include "cocos2d.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"

USING_NS_CC;
using namespace cocos2d::ui;

class TreeNode;
class Tree : public ScrollView
{
public:
	static Tree* create();
	void createRoot(const std::string& strName = "", int width = 150, int height = 20, int space = 0, bool isHide = false);
	void addFirstLayerNode( const std::string& strName = "",
		int width = 150, int height = 20, int space = 0, bool isHide = false);
	void addSecondLayerNode( int secondIdx = -1, const std::string& strName = "",
		int width = 150, int height = 20, int space = 0, bool isHide = false);
	void addThirdLayerNode( int secondIdx = -1, int thirdIdx = -1, const std::string& strName = "",
		int width = 150, int height = 20, int space = 0, bool isHide = false);

	TreeNode* getRootNode() { return rootNode; }
protected:
	Tree();
	~Tree();
	bool init();
	virtual void initRenderer() override;

	void handleUpdate(EventCustom* e);
private:
 	int _height;
	TreeNode* rootNode;
};

#include "Tree.h"
#include "TreeNode.h"


Tree::Tree()
	: rootNode(nullptr)
	, _height(0)
{
}

Tree::~Tree()
{
	
}

bool Tree::init()
{
	ScrollView::init();
	//
	
	return true;
}

void Tree::createRoot(const std::string& strName, int width, int height, int space, bool isHide)
{
	_height = height;
	rootNode = TreeNode::createEx(nullptr, strName, width, height, space, isHide);
	int posY = this->getContentSize().height;
	rootNode->setPosition(Vec2(0, posY - height));
	this->addChild(rootNode);
	EventListenerCustom* _listener1;
	_listener1 = EventListenerCustom::create("TreeChanged", CC_CALLBACK_1(Tree::handleUpdate, this));
	rootNode->getEventDispatcher()->addEventListenerWithFixedPriority(_listener1, 1);
}

void Tree::addFirstLayerNode(const std::string& strName,
	int width, int height, int space, bool isHide)
{
	rootNode->addNode(TreeNode::createEx(rootNode, strName, width, height, space, isHide));
}

void Tree::addSecondLayerNode(int secondIdx, const std::string& strName ,
	int width, int height, int space, bool isHide)
{
	rootNode->getNodeByIndex(secondIdx)->addNode(TreeNode::createEx(rootNode, strName, width, height, space, isHide));
}

void Tree::addThirdLayerNode(int secondIdx, int thirdIdx, const std::string& strName,
	int width, int height, int space, bool isHide)
{

}


Tree* Tree::create()
{
	Tree* widget = new (std::nothrow) Tree();
	if (widget && widget->init())
	{
		widget->setDirection(Direction::VERTICAL);
		widget->setInertiaScrollEnabled(true);
		widget->autorelease();
		return widget;
	}
	CC_SAFE_DELETE(widget);
	return nullptr;
}

void Tree::handleUpdate(EventCustom* e)
{
	int newHeight = 0;
	if(rootNode)
	{
		Size cSize = this->getContentSize();

		newHeight = rootNode->getListHeight();
		this->setInnerContainerSize(Size(cSize.width, newHeight));
		
		if(cSize.height > newHeight)
		{
			rootNode->setPosition(Vec2(0, cSize.height - _height));
		}
		else
		{
			rootNode->setPosition(Vec2(0, newHeight - _height));
		}
		
		this->jumpToTop();
	} 
}

void Tree::initRenderer()
{
	ScrollView::initRenderer();
}

#include "cocos2d.h"
#include "cocostudio/CocoStudio.h"
#include "ui/CocosGUI.h"

USING_NS_CC;
using namespace cocos2d::ui;


class TreeNode : public Layout
{
public:
	TreeNode(Layout* container, const std::string& data, int width = 150, int height = 20, int space = 0, bool _isHide = false);
	
	static TreeNode* createEx(Layout* container, const std::string& data, int width, int height, int space = 0, bool isHide = false);
	
	void selected();

	bool isOpen() { return _bOpen; };
	void setValue(const std::string& o);
	const std::string& getValue() { return _value;  }

	TreeNode* getNodeByIndex(int index);
	void addNode(TreeNode* node);
	void removeNode(TreeNode* node);
	
	void addEvents();
	void removeEvents();

	void updateList();
	void cleanList();
	void openList();
	void closeList();
	int getListHeight();
protected:
	bool init();

	bool onTouchBegan(Touch *touch, Event *unusedEvent);
	void onTouchEnded(Touch *touch, Event *unusedEvent);
	void onMouseMove(Event* e);
	void overHandler(Event* e);
	void outHandler(Event* e);
	void changeHandler(EventCustom* e);
	void selectedHandler(EventCustom* e);

	void unSelected();
public:
	ImageView* _bgSelected;//test
	ImageView* _bgOver;//test
protected:
	ImageView* _bg;

	Layout* _nodeContainer;
	bool _bOpen;
	bool _bHide;
	Layout* _c;
	std::string	 _value;
	std::vector
    
    
     
      nodeArr;
	TreeNode* _pNode;
private:
	TextField* _txt_Label;
	bool _bSelected;
	int _w;
	int _h;
	int	_space;
};

    
    

#include "TreeNode.h"

TreeNode::TreeNode(Layout* container,const std::string& data,int width,int height,int space,bool _isHide )
	:_bg(nullptr)
	,_value(data)
	,_w(width)
	,_h(height)
	,_space(space)
	,_bHide(_isHide)
	,_bOpen(true)
	,_bSelected(false)
	,_txt_Label(nullptr)
{
	_c = container ? container : this;
}

bool TreeNode::init()
{
	Layout::init();
	nodeArr.clear();

	_bg = ImageView::create("tree.png");//test
	_bg->setAnchorPoint(Vec2::ZERO);
	addChild(_bg);

	this->setContentSize(_bg->getContentSize());
	//

	_bgSelected = ImageView::create("select.png");//test
	_bgSelected->setAnchorPoint(Vec2::ZERO);
	_bgSelected->setVisible(false);
	addChild(_bgSelected);

	_bgOver = ImageView::create("over.png");//test
	_bgOver->setAnchorPoint(Vec2::ZERO);
	_bgOver->setVisible(false);
	addChild(_bgOver);

	//
	

	_nodeContainer = Layout::create();
	_nodeContainer->setPositionY(-_h);//change
	_nodeContainer->retain();//if don't want to be deleted ,then call retain , or call release 
	_nodeContainer->setAnchorPoint(Vec2::ZERO);
	this->addChild(_nodeContainer);

	if (!_bHide)
	{
		_txt_Label = TextField::create();
		_txt_Label->setPosition(Vec2(50, 3));
		_txt_Label->setTextColor(Color4B::YELLOW);
		_txt_Label->setAnchorPoint(Vec2::ZERO);
		_txt_Label->setEnabled(false);
		_txt_Label->setTextHorizontalAlignment(TextHAlignment::CENTER);
		addChild(_txt_Label);
	}

	setValue(_value);

	if (_bHide)
	{
		if(_bg) _bg->setVisible(false);
		_nodeContainer->setPositionY(0);
		this->setContentSize(Size(0, 0));
	}

	if (!_bHide) 
	{
		setValue(_value);
		_touchListener = EventListenerTouchOneByOne::create();
		_touchListener->onTouchBegan = CC_CALLBACK_2(TreeNode::onTouchBegan, this);
		_touchListener->onTouchEnded = CC_CALLBACK_2(TreeNode::onTouchEnded, this);
		_bg->getEventDispatcher()->addEventListenerWithFixedPriority(_touchListener, -1);
		_touchListener->retain();

		EventListenerMouse* _mouseListener = EventListenerMouse::create();
		_mouseListener->onMouseMove = CC_CALLBACK_1(TreeNode::onMouseMove, this);
		_bg->getEventDispatcher()->addEventListenerWithFixedPriority(_mouseListener, -1);
		_mouseListener->retain();
	}

	EventListenerCustom* _listener1;
	EventListenerCustom* _listener2;
	_listener1 = EventListenerCustom::create("TreeChanged", CC_CALLBACK_1(TreeNode::changeHandler, this));
	_listener2 = EventListenerCustom::create("TreeSelected", CC_CALLBACK_1(TreeNode::selectedHandler, this));
	_c->getEventDispatcher()->addEventListenerWithFixedPriority(_listener1, 1);
	_c->getEventDispatcher()->addEventListenerWithFixedPriority(_listener2, 1);

	return true;
}

TreeNode* TreeNode::createEx(Layout* container, const std::string& data, int width, int height, int space, bool isHide)
{
	TreeNode * _node1 = new TreeNode(container, data, width, height, space, isHide);
	_node1->setAnchorPoint(Vec2::ZERO);
	_node1->init();

	return _node1;
}

void TreeNode::addEvents()
{
}
void TreeNode::removeEvents()
{
}

void TreeNode::addNode(TreeNode* node)
{
	if((int)nodeArr.size() > 0)
	{
		node->setPositionY( nodeArr[nodeArr.size() - 1]->getPositionY() - node->_h - _space );
	}
	else
	{
		node->setPositionY(0);
	}

	node->_pNode = this;
	
	//
	int heightOffset = _nodeContainer->getContentSize().height + node->getContentSize().height;
	
	//
	_nodeContainer->addChild(node);
	_nodeContainer->setContentSize(Size(node->getContentSize().width, heightOffset));
	nodeArr.push_back(node);

	EventCustom event("TreeChanged");
	_c->getEventDispatcher()->dispatchEvent(&event);


	if((int)nodeArr.size() == 1)
	{
		if(_bg) _bg->setEnabled(true);
	}
}
void TreeNode::removeNode(TreeNode* node)
{
	std::vector
   
   
    
    ::iterator it;
	for(it = nodeArr.begin(); it != nodeArr.end(); ++it)
	{
		TreeNode* tmp = *it;
		if(tmp == node)
		{
			nodeArr.erase(it);
			//
			int heightOffset = _nodeContainer->getContentSize().height - node->getContentSize().height;
			_nodeContainer->removeChild(tmp, true);
			_nodeContainer->setContentSize(Size(node->getContentSize().width, heightOffset));
			//
			EventCustom event("TreeChanged");
			_c->getEventDispatcher()->dispatchEvent(&event);

			if ((int)nodeArr.size() == 0) 
			{
				if(_bg) _bg->setEnabled(false);
			}
			break;
		}
	}
}
void TreeNode::updateList()
{
	cleanList();
	TreeNode* currentNode;
	TreeNode* prevNode;
	for(int i = 0;i < (int)nodeArr.size();i++)
	{
		currentNode = nodeArr[i];
		currentNode->setPositionX(0);
		currentNode->updateList();
		if(i == 0)
		{
			currentNode->setPositionY( 0 );
		}
		else
		{
			prevNode = nodeArr[i-1];
			int nextPosY = nextPosY = prevNode->getPositionY() - prevNode->getContentSize().height - _space;
			if(prevNode->isOpen())
			{
				nextPosY = nextPosY - prevNode->_nodeContainer->getContentSize().height;
			}
			
			currentNode->setPositionY( nextPosY );
		}
	
		_nodeContainer->addChild(currentNode);
	}
}
void TreeNode::cleanList()
{
	for(int i = 0; i < (int)nodeArr.size(); ++i)
	{
		TreeNode* tmp = nodeArr[i];
		if(tmp)
		{
			_nodeContainer->removeChild(tmp, false);
		}
	}
}

void TreeNode::openList(){
	_bOpen = true;

	this->addChild(_nodeContainer);

	EventCustom event("TreeChanged");
	_c->getEventDispatcher()->dispatchEvent(&event);
}

void TreeNode::closeList()
{
	_bOpen = false;
	this->removeChild(_nodeContainer, false);
	
	EventCustom event("TreeChanged");
	_c->getEventDispatcher()->dispatchEvent(&event);
}

bool TreeNode::onTouchBegan(Touch *touch, Event *unusedEvent)
{
	Point _touchStartPos = touch->getLocation();
	Point nsp = convertToNodeSpace(_touchStartPos);
	Rect bb;
	bb.size = _bg->getContentSize();
	if (bb.containsPoint(nsp))
	{
		return true;
	}
	return false;
}

void TreeNode::onTouchEnded(Touch *touch, Event *unusedEvent)
{
	if ((int)nodeArr.size() > 0) {
		_bOpen ? closeList() : openList();
	}
	else {
		//EventCustom event("TreeSelected");
		//event.setUserData(this);
		//_c->getEventDispatcher()->dispatchEvent(&event);
	}
	EventCustom event("TreeSelected");
	event.setUserData(this);
	_c->getEventDispatcher()->dispatchEvent(&event);
}

void TreeNode::onMouseMove(Event* e)
{
	auto mouseEvent = static_cast
    
    
     
     (e);
	float x = mouseEvent->getCursorX();
	float y = mouseEvent->getCursorY();
	Point _touchStartPos(x, y);
	Point nsp = convertToNodeSpace(_touchStartPos);

	Rect bb;
	bb.size = _bg->getContentSize();
	if (bb.containsPoint(nsp))
	{
		if ((int)nodeArr.size() > 0)
		{
			_bgOver->setVisible(false);
			return;
		}
		if (_bSelected) { return; }

		_bgOver->setVisible(true);
	}
	else
	{
		//if (_bSelected) { return; }
		_bgOver->setVisible(false);
	}
}

void TreeNode::changeHandler(EventCustom* e)
{
	updateList();
}
void TreeNode::selectedHandler(EventCustom* e)
{
	if ((int)nodeArr.size() > 0) {
		return;
	}
	unSelected();

	void* data = e->getUserData();
	TreeNode* tmp = static_cast
     
     
      
      (data);
	tmp->selected();
}
void TreeNode::unSelected()  
{
	_bSelected = false;
	_bgSelected->setVisible(false);
}

void TreeNode::selected()
{
	_bSelected = true;

	if ((int)nodeArr.size() > 0) {
		return;
	}
	_bgSelected->setVisible(true);
	_bgOver->setVisible(false);
}

TreeNode* TreeNode::getNodeByIndex(int index)
{
	if (index < 0 || index >= (int)nodeArr.size())
	{
		return nullptr;
	}
	return nodeArr[index];
}

int TreeNode::getListHeight()
{
	TreeNode* node;
	int iListHeight = 0;
	for (int i = 0;i < (int)nodeArr.size();i++)
	{
		node = nodeArr[i];
		iListHeight += node->getContentSize().height + _space;
		
	
		if (node->isOpen())
		{
			iListHeight += node->getListHeight();
		}
	}
	return iListHeight;
}

void TreeNode::setValue(const std::string& o)
{
	_value = o;  
	if (_txt_Label) _txt_Label->setString(o);
}

     
     
    
    
   
   

使用如下:

//1

Tree* _tree = Tree::create();
_tree->setPosition(Vec2(100, 100));
this->addChild(_tree);
_tree->setContentSize(Size(150, 100));
_tree->createRoot("root", 120, 22, 0, true);


_tree->addFirstLayerNode("A", 120, 22);
_tree->addFirstLayerNode("B", 120, 22);
_tree->addFirstLayerNode("C", 120, 22);


_tree->addSecondLayerNode(0, "AA", 120, 22);


_tree->addSecondLayerNode(1, "BA", 120, 22);
_tree->addSecondLayerNode(1, "BB", 120, 22);


_tree->addSecondLayerNode(2, "CA", 120, 22);
_tree->addSecondLayerNode(2, "CB", 120, 22);
_tree->addSecondLayerNode(2, "CC", 120, 22);

//2

cocos2d::EventListenerCustom* _listener = EventListenerCustom::create("TreeSelected", CC_CALLBACK_1(HelloWorld::selectedHandler, this));
_tree->getRootNode()->getEventDispatcher()->addEventListenerWithFixedPriority(_listener, 1);

//3

void HelloWorld::selectedHandler(EventCustom* e) 
{
static_cast<TreeNode*>(e->getUserData())->getValue();

}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值