您的位置:首页 > 移动开发 > Cocos引擎

cocos2d-x tree 控件实现

2016-10-20 12:02 169 查看
闲来无聊码码代码 哈哈

使用的是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();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息