cocos2dx伸缩式列表效果
效果:
代码:
ElasticListView.h
#pragma once //std #include <string> #include <map> //cocos #include "cocos2d.h" #include "cocostudio/CocoStudio.h" #include "ui/CocosGUI.h" //self //#include "studioUi/StudioUiBase.h" using namespace std; USING_NS_CC; using namespace cocos2d::ui; using namespace cocostudio; using namespace cocostudio::timeline; //列表项 class ElasticItem { public: ElasticItem(); virtual ~ElasticItem(); //清理 void Clear(); //创建ElasticList static ElasticItem* Create(Node *pRoot, Widget::ccWidgetTouchCallback callback,int itemIndex); //SetIsHaveExtTxt static void SetIsHaveExtTxt(bool isHave){ IsHaveExtTxt = isHave; } //初始化 virtual bool Init(Node *pRoot, Widget::ccWidgetTouchCallback callback,int itemIndex); public: //设置列表值 void SetValue(int value){ _ElasticItemValue = value; } ///获取列表值 int GetValue(){ return _ElasticItemValue; } //设置列表名称 void SetItemName(const char *pName); //设置列表名称颜色 void SetItemNameColor(const Color3B& color); //设置列表扩展文本 void SetExtTxt(const char *pName); //设置扩展文本颜色 void SetSetExtTxtColor(const Color3B& color); //设置扩展文本是否可见 void SetExtTextVisible(bool bset); //获取控件根节点 Node *GetRootNode(){ return _pElasticItemBtn; } //设置位置 void SetPos(Vec2 &pos){ _pElasticItemBtn->setPosition(pos); } //显示隐藏 void Show(bool bShow){ _pElasticItemBtn->setVisible(bShow); } //选中处理 void OnSelect(); //取消选中处理 void OnCancleSelect(); //更新item文本位置 void UpdateItemTxtPos(); protected: // static bool IsHaveExtTxt; //是否有扩展Txt int _itemIndex; //列表项索引 int _ElasticItemValue; //列表项值 //ui Text* _pItemNameTxt; //ItemNameTxt Text* _pExtTxt; //扩展Txt ui::Button* _pElasticItemBtn; //列表项按钮 }; typedef map<int, ElasticItem*> ElasticItemMap; //列表子项 class ElasticListView; //弹出式列表 class ElasticList { public: //弹出弹入类型 enum ActionType { ActionNone=0, //没有动作 ActionOut, //弹出 ActionIn, //弹入 }; //item list 状态 enum ItemListState { ListStateOut = 0, //弹出 ListStateIn, //弹入 }; public: ElasticList(); virtual ~ElasticList(); //创建 static ElasticList* Create(int listIndex, ElasticListView *pElasticListView); //初始化 virtual bool Init(int listIndex, ElasticListView *pElasticListView); public: //设置列表值 void SetValue(int value){ _elasticListValue = value; } //获取列表值 int GetValue(){ return _elasticListValue; } //设置listIndex void SetListIndex(int value){ _listIndex = value; } //获取listIndex int GetListIndex(){ return _listIndex; } //设置列表名称 void SetListName(const char *pName); //获取控件根节点 Node *GetRootNode(){ return _pListPanel; } //获取ListSize Size GetListSize(){ return _pListPanel->getContentSize(); } //获取List高度 float GetListHeight(){ return _totalHeight; } //设置位置 void SetPos(Vec2 &pos){ _pListPanel->setPosition(pos); } //更新ElasticItem void UpdateElasticItem(); //更新ElasticItem txt pos void UpdateElasticItemTxtPos(); //更新 void Update(float dt); //item touch callback void OnItemTouch(Ref* pSender, Widget::TouchEventType touchuType); //listname touch callback void OnListNameTouch(Ref* pSender, Widget::TouchEventType touchuType); //改变list state void ChangeListState(ItemListState tarState); //是否正在伸缩list bool IsElasticing(); //清理 void Clear(); //选中item void SelectItem(ElasticItem *pItem); //获取item ElasticItem *GetItem(int itemIndex); //添加item ElasticItem *AddItem(int itemIndex); //删除item void DelItem(int itemIndex); protected: //弹出更新 void ActionOutUpdate(float dt); //弹入更新 void ActionInUpdate(float dt); protected: //data static const int NameVerticalPanding = 10; //listname上方间距 static const int ItemVerticalPanding = 6; //ElasticItem上方间距 static float ScaleSteep; //缩放系数 bool _needUpdateUi; //需要更新ui int _elasticListValue; //列表值 int _listIndex; //list索引 float _totalHeight; //总高度 ElasticListView *_pElasticListView; //ElasticListView指针 //action ActionType _curActionType; //当前动作类型 ItemListState _curListState; //当前list状态 //ui Layout *_pListPanel; //列表容器 ui::Button *_pListName; //列表名 ElasticItemMap _itemList; //子项列表 }; typedef map<int, ElasticList*> ElasticListMap; //列表map typedef std::function<void(int)> ElasticItemListener; //弹出式列表视图,内含多个ElasticList class ElasticListView { public: ElasticListView(); virtual ~ElasticListView(); //获取list克隆控件 Widget *GetElasticListClone(){ return _pElasticListClone; } //获取item克隆控件 Widget *GetElasticItemClone(){ return _pElasticItemClone; } //创建ElasticList void AddElasticList(ElasticList *pElasticList); //获取ElasticList ElasticList * GetElasticList(int index); public: //初始化 bool Init(Node *pRoot); //注册更新 void RigisterUpdate(); //更新 void Update(float dt); //更新ElasticList void UpdateElasticList(); //是否正在缩放list bool IsElasticingList(){ return _isElasticing; } //设置是否正在缩放list void SetIsElasticingList(bool bSet); //保存ScrollView百分比位置 void SaveScrollViewPercent(); //恢复ScrollView百分比位置 void RecoveryScrollViewPercent(); //开始伸缩前的准备 void PrepareElastic(); //是否可以伸缩 bool CanElasticList(); //设置选中项 void SetCurSelectItem(ElasticItem *pItem); //设置选中项 void SetCurSelectItem(int listIndex, int itemIndex); //获取选中项 ElasticItem *GetCurSelectItem(){ return _pCurSelectItem; } //设置选中监听回调 void SetItemListener(const ElasticItemListener &listener){ _pSelItemListener = listener; } //清理 void Clear(); protected: ElasticListMap _elasticListMap; //列表map static const int VerticalPanding = 10; //ElasticList垂直间距 float _totalHeight; //总高度 bool _isElasticing; //正在缩放list float _scrollViewPercent; //ScrollView百分比位置 ElasticItemListener _pSelItemListener; //选中item事件 ElasticItem *_pCurSelectItem; //当前选中的item //ui Widget *_pElasticListClone; //elasticList clone Widget *_pElasticItemClone; //elasticItem clone ui::ScrollView *_pConScrollView; //ScrollView容器 };
ElasticListView.cpp
#include "ElasticListView.h" //self #include "studioUi/commonFun/ComUiFun.h" using namespace StudioComFunSpce; //-------------ElasticItem--------------------------------------------- bool ElasticItem::IsHaveExtTxt=false; ElasticItem::ElasticItem() { _ElasticItemValue = 0; _itemIndex = 0; _pElasticItemBtn = nullptr; _pItemNameTxt = nullptr; _pExtTxt = nullptr; } ElasticItem::~ElasticItem() { } void ElasticItem::Clear() { _pElasticItemBtn->removeFromParentAndCleanup(0); } ElasticItem* ElasticItem::Create(Node *pRoot, Widget::ccWidgetTouchCallback callback, int itemIndex) { ElasticItem * pRet = nullptr; ElasticItem * pElasticItem = new (std::nothrow) ElasticItem(); if (pElasticItem && pElasticItem->Init(pRoot, callback,itemIndex)) { pRet = pElasticItem; } else { CC_SAFE_DELETE(pRet); } return pRet; } bool ElasticItem::Init(Node *pRoot, Widget::ccWidgetTouchCallback callback, int itemIndex) { bool ret = false; do { _pElasticItemBtn = static_cast<ui::Button*>(pRoot); CC_BREAK_IF(!_pElasticItemBtn || !callback); Node *pNode = nullptr; // _itemIndex = itemIndex; //btnTxt pNode = FindUiChildNode(_pElasticItemBtn, "btnTxt"); _pItemNameTxt = static_cast<Text*>(pNode); CC_BREAK_IF(!_pItemNameTxt); //extBtnTxt0 if (IsHaveExtTxt) { pNode = FindUiChildNode(_pElasticItemBtn, "extBtnTxt0"); _pExtTxt = static_cast<Text*>(pNode); CC_BREAK_IF(!_pExtTxt); } //UserData _pElasticItemBtn->setUserData(this); //event _pElasticItemBtn->addTouchEventListener(callback); ret = true; } while (0); return ret; } void ElasticItem::SetItemName(const char *pName) { if (_pItemNameTxt) { _pItemNameTxt->setString(pName); } } void ElasticItem::SetItemNameColor(const Color3B& color) { if (_pItemNameTxt) { _pItemNameTxt->setColor(color); } } void ElasticItem::SetExtTxt(const char *pName) { if (_pExtTxt) { _pExtTxt->setString(pName); } } void ElasticItem::SetExtTextVisible(bool bset) { if (_pExtTxt) { _pExtTxt->setVisible(bset); } } void ElasticItem::SetSetExtTxtColor(const Color3B& color) { if (_pExtTxt) { _pExtTxt->setColor(color); } } void ElasticItem::OnSelect() { _pElasticItemBtn->setBright(false); _pElasticItemBtn->setEnabled(false); } void ElasticItem::OnCancleSelect() { _pElasticItemBtn->setBright(true); _pElasticItemBtn->setEnabled(true); } void ElasticItem::UpdateItemTxtPos() { bool bOnelyNameTxt = true; Size itemSize = _pElasticItemBtn->getContentSize(); Size nameTxtSize = _pItemNameTxt->getContentSize(); Size extTxtSize; Vec2 naemPos(itemSize.width / 2, itemSize.height / 2); Vec2 extPos = naemPos; if (_pExtTxt&&_pExtTxt->isVisible()) { bOnelyNameTxt = false; extTxtSize = _pExtTxt->getContentSize(); } //只有ItemNameTxt if (bOnelyNameTxt) { naemPos.x = (itemSize.width - nameTxtSize.width) / 2; _pItemNameTxt->setPosition(naemPos); } else { naemPos.x = (itemSize.width - nameTxtSize.width - extTxtSize.width) / 2; extPos.x = naemPos.x + nameTxtSize.width + 2; _pItemNameTxt->setPosition(naemPos); _pExtTxt->setPosition(extPos); } } //-------------ElasticList--------------------------------------------- float ElasticList::ScaleSteep=0.04f; ElasticList::ElasticList() { _pListPanel = nullptr; _pListName = nullptr; _pElasticListView = nullptr; _needUpdateUi = false; _listIndex = 0; _elasticListValue = 0; _totalHeight = 0; _curListState = ListStateOut; _curActionType = ActionNone; } ElasticList::~ElasticList() { //释放内存 ElasticItemMap::iterator it; ElasticItem* pElasticItem = nullptr; for (it = _itemList.begin(); it != _itemList.end();) { pElasticItem = it->second; pElasticItem->Clear(); CC_SAFE_DELETE(pElasticItem); it = _itemList.erase(it); } } void ElasticList::Clear() { _needUpdateUi = true; _curListState = ListStateOut; _curActionType = ActionNone; //更新容器高度 _totalHeight = _pListName->getContentSize().height + NameVerticalPanding * 2; Size panelSize = _pListPanel->getContentSize(); panelSize.height = _totalHeight; _pListPanel->setContentSize(panelSize); //释放内存 ElasticItemMap::iterator it; ElasticItem* pElasticItem = nullptr; for (it = _itemList.begin(); it != _itemList.end();) { pElasticItem = it->second; pElasticItem->Clear(); CC_SAFE_DELETE(pElasticItem); it = _itemList.erase(it); } _itemList.clear(); } ElasticList* ElasticList::Create(int listIndex, ElasticListView *pElasticListView) { ElasticList * pRet = nullptr; ElasticList * pElasticList = new (std::nothrow) ElasticList(); if (pElasticList && pElasticList->Init(listIndex, pElasticListView)) { pRet = pElasticList; } else { CC_SAFE_DELETE(pRet); } return pRet; } bool ElasticList::Init(int listIndex, ElasticListView *pElasticListView) { bool ret = false; do { CC_BREAK_IF(!pElasticListView); _listIndex = listIndex; _pElasticListView = pElasticListView; //变量 char tc[128] = {0}; Node *pNode = nullptr; Widget *pElasticItemClone = nullptr; int itemHeight = 0; //获取克隆控件 Widget *pElasticListClone = pElasticListView->GetElasticListClone(); CC_BREAK_IF(!pElasticListClone); //ElasticList克隆控件 Widget *pElasticListTemp = pElasticListClone->clone(); CC_BREAK_IF(!pElasticListTemp); pElasticListTemp->setVisible(true); //修改控件名 sprintf(tc, "elasticList%d", _listIndex); pElasticListTemp->setName(tc); //elasticList _pListPanel = static_cast<Layout*>(pElasticListTemp); CC_BREAK_IF(!_pListPanel); //elasticListName pNode = FindUiChildNode(pElasticListTemp, "elasticListName"); _pListName = static_cast<ui::Button*>(pNode); CC_BREAK_IF(!_pListName); Widget::ccWidgetTouchCallback nameCallback = CC_CALLBACK_2(ElasticList::OnListNameTouch, this); _pListName->addTouchEventListener(nameCallback); //更新高度 _totalHeight = _totalHeight + _pListName->getContentSize().height + NameVerticalPanding* 2; //elasticItem pNode = FindUiChildNode(pElasticListTemp, "elasticItem"); pElasticItemClone = static_cast<Widget*>(pNode); CC_BREAK_IF(!pElasticItemClone); //itemHeight = pElasticItemClone->getContentSize().height + ItemVerticalPanding; //设置更新标记 _needUpdateUi = true; //删除item pElasticListTemp->removeChild(pElasticItemClone); ret = true; } while (0); return ret; } ElasticItem *ElasticList::AddItem(int itemIndex) { ElasticItem* pElasticItem = nullptr; do { //变量 char tc[128] = { 0 }; Node *pNode = nullptr; Widget *pElasticItemClone = nullptr; int itemHeight = 0; //elasticItem克隆控件 pElasticItemClone = _pElasticListView->GetElasticItemClone(); CC_BREAK_IF(!pElasticItemClone); itemHeight = pElasticItemClone->getContentSize().height + ItemVerticalPanding; //更新高度 _totalHeight = _totalHeight + itemHeight; Widget *pElasticItemTemp = pElasticItemClone->clone(); CC_BREAK_IF(!pElasticItemTemp); //callback Widget::ccWidgetTouchCallback callback = CC_CALLBACK_2(ElasticList::OnItemTouch, this); //创建ElasticItem pElasticItem = ElasticItem::Create(pElasticItemTemp, callback, itemIndex); CC_BREAK_IF(!pElasticItem); //修改控件名 sprintf(tc, "elasticItem%d", itemIndex); pElasticItemTemp->setName(tc); //添加 _pListPanel->addChild(pElasticItem->GetRootNode()); _itemList[itemIndex] = pElasticItem; //设置更新标记 _needUpdateUi = true; } while (0); return pElasticItem; } void ElasticList::DelItem(int itemIndex) { ElasticItemMap::iterator it = _itemList.find(itemIndex); if (it != _itemList.end()) { _itemList.erase(it); //设置更新标记 _needUpdateUi = true; } } void ElasticList::SetListName(const char *pName) { do { CC_BREAK_IF(!pName); Node *pNode = nullptr; Text *pText = nullptr; //btnTxt pNode = FindUiChildNode(_pListName, "btnTxt"); pText = static_cast<Text*>(pNode); CC_BREAK_IF(!pText); pText->setString(pName); } while (0); } void ElasticList::UpdateElasticItemTxtPos() { //更新ElasticItem txt位置 ElasticItemMap::iterator it; for (it = _itemList.begin(); it != _itemList.end();it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) { pElasticItem->UpdateItemTxtPos(); } } } void ElasticList::UpdateElasticItem() { int totalHeight = _totalHeight; Size panelSize = _pListPanel->getContentSize(); Size nameSizes = _pListName->getContentSize(); Vec2 pos(panelSize.width/2,0); //更新ListName位置 pos.y = totalHeight - NameVerticalPanding; _pListName->setPosition(pos); totalHeight = totalHeight - NameVerticalPanding - nameSizes.height; //更新ElasticItem位置 ElasticItemMap::iterator it; for (it = _itemList.begin(); it != _itemList.end();it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) { Size itemSizes = pElasticItem->GetRootNode()->getContentSize(); pos.y = totalHeight - ItemVerticalPanding; pElasticItem->SetPos(pos); totalHeight = totalHeight - ItemVerticalPanding - itemSizes.height; } } //更新容器高度 panelSize.height = _totalHeight; _pListPanel->setContentSize(panelSize); //更新ElasticList _pElasticListView->UpdateElasticList(); } void ElasticList::OnListNameTouch(Ref* pSender, Widget::TouchEventType touchuType) { do { ui::Button *pBtn = static_cast<ui::Button*>(pSender); CC_BREAK_IF(!pBtn); if (touchuType == Widget::TouchEventType::BEGAN) { pBtn->setScale(1.2f); } else if (touchuType == Widget::TouchEventType::CANCELED) { pBtn->setScale(1.0f); } else if (touchuType == Widget::TouchEventType::MOVED) { } else if (touchuType == Widget::TouchEventType::ENDED) { pBtn->setScale(1.0f); // if (_itemList.size()>0) { if (_curActionType == ActionNone&&_pElasticListView->CanElasticList()) { if (_curListState == ListStateIn) { ChangeListState(ListStateOut); } else if (_curListState == ListStateOut) { ChangeListState(ListStateIn); } } } } } while (0); } void ElasticList::OnItemTouch(Ref* pSender, Widget::TouchEventType touchuType) { do { ui::Button *pBtn = static_cast<ui::Button*>(pSender); CC_BREAK_IF(!pBtn); if (touchuType == Widget::TouchEventType::BEGAN) { } else if (touchuType == Widget::TouchEventType::CANCELED) { } else if (touchuType == Widget::TouchEventType::MOVED) { } else if (touchuType == Widget::TouchEventType::ENDED) { void *p = pBtn->getUserData(); //int *pValue = (int*)p; ElasticItem *pItem = (ElasticItem*)p;; CC_BREAK_IF(!pItem); //选中 SelectItem(pItem); } } while (0); } void ElasticList::SelectItem(ElasticItem *pItem) { do { CC_BREAK_IF(!pItem); ElasticItem *pLastItem = _pElasticListView->GetCurSelectItem(); if (pItem != pLastItem) { //取消选中处理 if (pLastItem) pLastItem->OnCancleSelect(); //选中处理 pItem->OnSelect(); //保存指针 _pElasticListView->SetCurSelectItem(pItem); } } while (0); } bool ElasticList::IsElasticing() { bool ret = false; if (_curActionType != ActionNone) ret = true; return ret; } ElasticItem * ElasticList::GetItem(int itemIndex) { ElasticItem *pRet = nullptr; do { ElasticItem* pItem = _itemList.at(itemIndex); CC_BREAK_IF(!pItem); pRet = pItem; } while (0); return pRet; } void ElasticList::ChangeListState(ItemListState tarState) { if (_curActionType == ActionNone&&_curListState != tarState) { if (tarState == ListStateIn) { _curActionType = ActionIn; //设置正在缩放 _pElasticListView->SetIsElasticingList(true); } else if (tarState == ListStateOut) { _curActionType = ActionOut; //设置正在缩放 _pElasticListView->SetIsElasticingList(true); //ElasticItem处理 ElasticItemMap::iterator it; for (it = _itemList.begin(); it != _itemList.end();it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) pElasticItem->Show(true); } } } } void ElasticList::Update(float dt) { if (_needUpdateUi) { //更新ElasticItem UpdateElasticItem(); _needUpdateUi = false; } if (_curActionType != ActionNone) { if (_curActionType == ActionIn) ActionInUpdate(dt); else if (_curActionType == ActionOut) ActionOutUpdate(dt); } } void ElasticList::ActionOutUpdate(float dt) { do { int count = _itemList.size(); CC_BREAK_IF(count == 0); ElasticItemMap::iterator it = _itemList.begin(); ElasticItem* pFirstItem = it->second; CC_BREAK_IF(!pFirstItem); //scale static float totalScale = 0.01f; totalScale += ScaleSteep; float verticalPanding = ItemVerticalPanding*totalScale; // Size panelSize = _pListPanel->getContentSize(); Size nameSizes = _pListName->getContentSize(); Size itemSize = pFirstItem->GetRootNode()->getContentSize(); float totalHeight = (itemSize.height + ItemVerticalPanding)*totalScale*count + (nameSizes.height + NameVerticalPanding * 2); Vec2 pos(panelSize.width / 2, 0); //更新容器高度 panelSize.height = totalHeight; _pListPanel->setContentSize(panelSize); //更新ListName位置 pos.y = totalHeight - NameVerticalPanding; _pListName->setPosition(pos); totalHeight = totalHeight - NameVerticalPanding - nameSizes.height; //更新ElasticItem位置 for (it = _itemList.begin(); it != _itemList.end(); it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) { Node *pItemRoot = pElasticItem->GetRootNode(); //scale pItemRoot->setScaleY(totalScale); //size Size itemSizes = pItemRoot->getContentSize(); pos.y = totalHeight - verticalPanding; pElasticItem->SetPos(pos); totalHeight = totalHeight - verticalPanding - itemSizes.height*totalScale; } } //结束处理 if (totalScale >= 0.95f) { //ElasticItem处理 for (it = _itemList.begin(); it != _itemList.end(); it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) { Node *pItemRoot = pElasticItem->GetRootNode(); //scale pItemRoot->setScaleY(1.0f); } } //更新ElasticItem UpdateElasticItem(); //更新ElasticListView _pElasticListView->UpdateElasticList(); //设置结束缩放 _pElasticListView->SetIsElasticingList(false); //状态设置 _curActionType = ActionNone; _curListState = ListStateOut; totalScale = 0.01f; } } while (0); } void ElasticList::ActionInUpdate(float dt) { do { int count = _itemList.size(); CC_BREAK_IF(count==0); ElasticItemMap::iterator it =_itemList.begin(); ElasticItem* pFirstItem = it->second; CC_BREAK_IF(!pFirstItem); //scale static float totalScale = 1.0f; totalScale -= ScaleSteep; float verticalPanding = ItemVerticalPanding*totalScale; // Size panelSize = _pListPanel->getContentSize(); Size nameSizes = _pListName->getContentSize(); Size itemSize = pFirstItem->GetRootNode()->getContentSize(); float totalHeight = (itemSize.height + ItemVerticalPanding)*totalScale*count + (nameSizes.height + NameVerticalPanding * 2); //totalHeight = (_totalHeight - nameSizes.height - VerticalPanding)*totalScale; Vec2 pos(panelSize.width / 2, 0); //更新容器高度 panelSize.height = totalHeight; _pListPanel->setContentSize(panelSize); //更新ListName位置 pos.y = totalHeight - NameVerticalPanding; _pListName->setPosition(pos); totalHeight = totalHeight - NameVerticalPanding - nameSizes.height; //更新ElasticItem位置 for (it = _itemList.begin(); it != _itemList.end(); it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) { Node *pItemRoot = pElasticItem->GetRootNode(); //scale pItemRoot->setScaleY(totalScale); //size Size itemSizes = pItemRoot->getContentSize(); pos.y = totalHeight - verticalPanding; pElasticItem->SetPos(pos); totalHeight = totalHeight - verticalPanding - itemSizes.height*totalScale; } } //结束处理 if (totalScale <= 0.01f) { //ElasticItem处理 for (it = _itemList.begin(); it != _itemList.end(); it++) { ElasticItem* pElasticItem = it->second; if (pElasticItem) pElasticItem->Show(false); } //更新容器高度 //_totalHeight = nameSizes.height + NameVerticalPanding * 2; panelSize.height = nameSizes.height + NameVerticalPanding * 2; _pListPanel->setContentSize(panelSize); //更新ListName位置 pos.y = panelSize.height - NameVerticalPanding; _pListName->setPosition(pos); //更新ElasticListView _pElasticListView->UpdateElasticList(); //设置结束缩放 _pElasticListView->SetIsElasticingList(false); //状态设置 _curActionType = ActionNone; _curListState = ListStateIn; totalScale = 1.0f; } } while (0); } //-------------ElasticListView--------------------------------------------- ElasticListView::ElasticListView() { _totalHeight = 0; _isElasticing = false; _pCurSelectItem = nullptr; _pSelItemListener = nullptr; _pElasticListClone = nullptr; } ElasticListView::~ElasticListView() { //取消更新 Director::getInstance()->getScheduler()->unschedule("ElasticListView::Update", this); //释放内存 ElasticListMap::iterator it; ElasticList* pElasticList=nullptr; for (it = _elasticListMap.begin(); it != _elasticListMap.end();) { pElasticList = it->second; CC_SAFE_DELETE(pElasticList); it = _elasticListMap.erase(it); } } void ElasticListView::Clear() { _pCurSelectItem = nullptr; _totalHeight = 0; _isElasticing = false; int count = _elasticListMap.size(); _totalHeight = 0; for (int i = 0; i < count; i++) { ElasticList* pElasticList = _elasticListMap.at(i); if (pElasticList) { pElasticList->Clear(); } } } bool ElasticListView::Init(Node *pRoot) { bool ret = false; do { CC_BREAK_IF(!pRoot); // Node *pNode = nullptr; //elasticListView pNode = FindUiChildNode(pRoot, "elasticListView"); _pConScrollView = static_cast<ui::ScrollView*>(pNode); _pConScrollView->SetBounceBackDuration(0.5f); //_pConScrollView->setBounceEnabled(false); //elasticListClone pNode = FindUiChildNode(_pConScrollView, "elasticListClone"); _pElasticListClone = static_cast<Widget*>(pNode); CC_BREAK_IF(!_pElasticListClone); _pElasticListClone->setVisible(false); //elasticItem pNode = FindUiChildNode(_pElasticListClone, "elasticItem"); _pElasticItemClone = static_cast<Widget*>(pNode); CC_BREAK_IF(!_pElasticItemClone); ret = true; } while (0); return ret; } void ElasticListView::RigisterUpdate() { //注册更新 ccSchedulerFunc updateCall = CC_CALLBACK_1(ElasticListView::Update, this); Director::getInstance()->getScheduler()->schedule(updateCall, this,0, false, "ElasticListView::Update"); } void ElasticListView::AddElasticList(ElasticList *pElasticList) { do { CC_BREAK_IF(!pElasticList); //char tc[128] = { 0 }; int index = pElasticList->GetListIndex(); ////set list name //sprintf(tc, "ElasticList%d", index); //pElasticList->SetListName(tc); //添加 _pConScrollView->addChild(pElasticList->GetRootNode()); _elasticListMap[index] = pElasticList; } while (0); } ElasticList* ElasticListView::GetElasticList(int index) { ElasticList* pRet = nullptr; ElasticListMap::iterator it = _elasticListMap.find(index); if (it!=_elasticListMap.end()) { pRet = it->second; } return pRet; } void ElasticListView::UpdateElasticList() { int count = _elasticListMap.size(); Size panelSize = _pConScrollView->getContentSize(); float totalHeight = 0; Vec2 pos(panelSize.width / 2, 0); //更新_totalHeight,itemtx pos _totalHeight = 0; for (int i = 0; i<count; i++) { ElasticList* pElasticList = _elasticListMap.at(i); if (pElasticList) { _totalHeight = _totalHeight + pElasticList->GetListSize().height + VerticalPanding; //itemtx pos pElasticList->UpdateElasticItemTxtPos(); } } //高度保护 if (_totalHeight < panelSize.height) { _totalHeight = panelSize.height+10; } totalHeight = _totalHeight; //更新ElasticList位置 for (int i = 0; i<count; i++) { ElasticList* pElasticList = _elasticListMap.at(i); if (pElasticList) { pos.y = totalHeight - VerticalPanding; pElasticList->SetPos(pos); totalHeight = totalHeight - VerticalPanding - pElasticList->GetListSize().height; } } //更新容器高度 panelSize.height = _totalHeight; _pConScrollView->setInnerContainerSize(panelSize); } void ElasticListView::Update(float dt) { bool bUpdateList = false; ElasticListMap::iterator it; for (it = _elasticListMap.begin(); it != _elasticListMap.end();it++) { it->second->Update(dt); if (it->second->IsElasticing()) bUpdateList=true; } if (bUpdateList) { UpdateElasticList(); } } void ElasticListView::SetIsElasticingList(bool bSet) { _isElasticing = bSet; //if (bSet) //{ // SaveScrollViewPercent(); //} //else //{ // RecoveryScrollViewPercent(); //} } void ElasticListView::SaveScrollViewPercent() { CCLOG("-----------------SaveScrollViewPercent--------------------"); Size panelSize = _pConScrollView->getContentSize(); Size innerSize = _pConScrollView->getInnerContainerSize(); Vec2 innerlPos = _pConScrollView->getInnerContainerPosition(); float minY = panelSize.height - innerSize.height; float h = -minY; float percent = innerlPos.y*100 / h; if (percent < 0) percent = -percent; _scrollViewPercent = percent; CCLOG("--panelSize:(%f,%f)", panelSize.width, panelSize.height); CCLOG("--innerSize:(%f,%f)", innerSize.width, innerSize.height); CCLOG("--innerlPos:(%f,%f)", innerlPos.x, innerlPos.y); CCLOG("--minY=%f,percent=%f", minY, percent); } void ElasticListView::RecoveryScrollViewPercent() { CCLOG("-----------------RecoveryScrollViewPercent--------------------"); Size panelSize = _pConScrollView->getContentSize(); Size innerSize = _pConScrollView->getInnerContainerSize(); Vec2 innerlPos = _pConScrollView->getInnerContainerPosition(); float minY = panelSize.height - innerSize.height; float h = -minY; float percent = innerlPos.y * 100 / h; if (percent < 0) percent = -percent; CCLOG("--panelSize:(%f,%f)", panelSize.width, panelSize.height); CCLOG("--innerSize:(%f,%f)", innerSize.width, innerSize.height); CCLOG("--innerlPos:(%f,%f)", innerlPos.x, innerlPos.y); CCLOG("--minY=%f,percent=%f", minY, percent); //_pConScrollView->scrollToPercentVertical(_scrollViewPercent, 0.5f,false); } void ElasticListView::PrepareElastic() { Size panelSize = _pConScrollView->getContentSize(); Size innerSize = _pConScrollView->getInnerContainerSize(); Vec2 innerlPos = _pConScrollView->getInnerContainerPosition(); float minY = panelSize.height - innerSize.height; //if (innerlPos.y>)ISAutoScrolling //{ //} } bool ElasticListView::CanElasticList() { bool ret = false; bool isScrooling = _pConScrollView->ISAutoScrolling(); bool isElasticing = IsElasticingList(); if (!isScrooling) { if (!isElasticing) { ret = true; } } return ret; } void ElasticListView::SetCurSelectItem(ElasticItem *pItem) { do { CC_BREAK_IF(!pItem); _pCurSelectItem = pItem; //选中item事件 if (_pSelItemListener) { _pSelItemListener(_pCurSelectItem->GetValue()); } } while (0); } void ElasticListView::SetCurSelectItem(int listIndex, int itemIndex) { do { ElasticList* pList = _elasticListMap.at(listIndex); CC_BREAK_IF(!pList); ElasticItem *pItem=pList->GetItem(itemIndex); CC_BREAK_IF(!pItem); _pCurSelectItem = pItem; //选中item事件 if (_pSelItemListener) { _pSelItemListener(_pCurSelectItem->GetValue()); } } while (0); }
使用代码,具体自己理解:
//创建ElasticListView------------------------------------------------- //char tc[128] = { 0 }; ElasticItem::SetIsHaveExtTxt(true); //初始化ElasticListView CC_BREAK_IF(!_elasticListView.Init(pConWinNode)); int langId[EUiTaskTypeCount]; //创建ElasticList for (int i = 0; i < EUiTaskTypeCount; i++) { ElasticList* pElasticList = ElasticList::Create(i, &_elasticListView); CC_BREAK_IF(!pElasticList); pElasticList->SetListName(GetStaticLangTxt(langId[i]).c_str()); pElasticList->SetValue(i); //add _elasticListView.AddElasticList(pElasticList); } //更新ElasticList //_elasticListView.UpdateElasticList(); //注册更新 _elasticListView.RigisterUpdate(); //注册选中事件 ElasticItemListener listener = CC_CALLBACK_1(TaskUiLayer::OnSelItem, this); _elasticListView.SetItemListener(listener); //创建设置ElasticItem ElasticItem *pItem = pElasticList->AddItem(pTblInfo->m_missionid); CC_BREAK_IF(!pItem); pItem->SetItemName(pTblInfo->m_name.c_str()); pItem->SetValue(pTblInfo->m_missionid);