效果:

代码:

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=, //没有动作
ActionOut, //弹出
ActionIn, //弹入
}; //item list 状态
enum ItemListState
{
ListStateOut = , //弹出
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 = ; //listname上方间距
static const int ItemVerticalPanding = ; //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 = ; //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 = ;
_itemIndex = ; _pElasticItemBtn = nullptr;
_pItemNameTxt = nullptr;
_pExtTxt = nullptr;
} ElasticItem::~ElasticItem()
{
}
void ElasticItem::Clear()
{ _pElasticItemBtn->removeFromParentAndCleanup();
} 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 (); 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 / , itemSize.height / );
Vec2 extPos = naemPos; if (_pExtTxt&&_pExtTxt->isVisible())
{
bOnelyNameTxt = false;
extTxtSize = _pExtTxt->getContentSize();
} //只有ItemNameTxt
if (bOnelyNameTxt)
{
naemPos.x = (itemSize.width - nameTxtSize.width) / ; _pItemNameTxt->setPosition(naemPos);
}
else
{
naemPos.x = (itemSize.width - nameTxtSize.width - extTxtSize.width) / ;
extPos.x = naemPos.x + nameTxtSize.width + ; _pItemNameTxt->setPosition(naemPos);
_pExtTxt->setPosition(extPos);
} } //-------------ElasticList--------------------------------------------- float ElasticList::ScaleSteep=0.04f; ElasticList::ElasticList()
{
_pListPanel = nullptr;
_pListName = nullptr;
_pElasticListView = nullptr; _needUpdateUi = false; _listIndex = ;
_elasticListValue = ; _totalHeight = ; _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 * ;
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[] = {};
Node *pNode = nullptr;
Widget *pElasticItemClone = nullptr;
int itemHeight = ; //获取克隆控件
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* ; //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 (); return ret;
} ElasticItem *ElasticList::AddItem(int itemIndex)
{
ElasticItem* pElasticItem = nullptr; do
{
//变量
char tc[] = { };
Node *pNode = nullptr;
Widget *pElasticItemClone = nullptr;
int itemHeight = ; //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 (); 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 ();
} 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/,); //更新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()>)
{
if (_curActionType == ActionNone&&_pElasticListView->CanElasticList())
{
if (_curListState == ListStateIn)
{
ChangeListState(ListStateOut);
}
else if (_curListState == ListStateOut)
{
ChangeListState(ListStateIn);
}
} } } } while ();
} 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 ();
} 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 (); } 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 (); 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 == );
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 * );
Vec2 pos(panelSize.width / , ); //更新容器高度
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 ();
} void ElasticList::ActionInUpdate(float dt)
{
do
{
int count = _itemList.size();
CC_BREAK_IF(count==);
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 * );
//totalHeight = (_totalHeight - nameSizes.height - VerticalPanding)*totalScale; Vec2 pos(panelSize.width / , ); //更新容器高度
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 * ;
_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 ();
} //-------------ElasticListView--------------------------------------------- ElasticListView::ElasticListView()
{
_totalHeight = ;
_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 = ;
_isElasticing = false; int count = _elasticListMap.size(); _totalHeight = ;
for (int i = ; 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 (); return ret;
} void ElasticListView::RigisterUpdate()
{
//注册更新
ccSchedulerFunc updateCall = CC_CALLBACK_1(ElasticListView::Update, this);
Director::getInstance()->getScheduler()->schedule(updateCall, this,, 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 ();
} 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 = ;
Vec2 pos(panelSize.width / , ); //更新_totalHeight,itemtx pos
_totalHeight = ;
for (int i = ; 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+;
}
totalHeight = _totalHeight; //更新ElasticList位置
for (int i = ; 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* / h; if (percent < )
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 * / h; if (percent < )
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 (); } 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 (); }

使用代码,具体自己理解:

        //创建ElasticListView-------------------------------------------------
//char tc[128] = { 0 }; ElasticItem::SetIsHaveExtTxt(true); //初始化ElasticListView
CC_BREAK_IF(!_elasticListView.Init(pConWinNode)); int langId[EUiTaskTypeCount]; //创建ElasticList
for (int i = ; 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);

cocos2dx伸缩式列表效果的更多相关文章

  1. Cocos2d-x实现粒子效果的三种方式

    在Cocos2d-x中,实现粒子效果可以有三种方法. Normal 0 10 pt 0 2 false false false EN-US ZH-CN X-NONE $([{£¥·'"〈&l ...

  2. AngularJS学习笔记(1)——MVC模式的清单列表效果

    MVC模式的清单列表效果 使用WebStorm新建todo.html并链入bootstrap.css.bootstrap-theme.css.angular.js.要链入的相关css和js文件预先准备 ...

  3. 实现移动端touch事件的横向滑动列表效果

    要实现手机端横向滑动效果并不难,了解实现的原理及业务逻辑就很容易实现.原理:touchstart(手指按下瞬间获取相对于页面的位置)——>touchmove(手指移动多少,元素相应移动多少). ...

  4. Cocos2d-x滚动列表具体解释(CCScrollView的使用)

    今天要写一个滚动列表功能,类似以下这样.(图片资源都是自己从天天酷跑里面抠的,仅用于学习方便) 首先,这样一个列表就和iOS里面的UITableView没什么两样,当然,Android中肯定也存在类似 ...

  5. React Native学习(七)—— FlatList实现横向滑动列表效果

    本文基于React Native 0.52 Demo上传到Git了,有需要可以看看,写了新内容会上传的.Git地址 https://github.com/gingerJY/React-Native-D ...

  6. (转载)自定义ExpandableListView,实现二级列表效果

    先看效果图: 上图是我们要实现的效果,那么现在我们开始着手去做,主要分为以下几步: 一丶我们需要根据效果图去思考该如何动手,从上图分析看,我们可以用一个相对布局RelativeLayout来完成gro ...

  7. 【深入篇】自定义ExpandableListView,实现二级列表效果

    先看效果图: 上图是我们要实现的效果,那么现在我们开始着手去做,主要分为以下几步: 一丶我们需要根据效果图去思考该如何动手,从上图分析看,我们可以用一个相对布局RelativeLayout来完成gro ...

  8. 用jeecg做个项目第二讲(Datagrid数据列表效果详解)

    1.列表界面 2.流程状态的效果 <t:dgCol title="流程状态" field="bpmStatus" queryMode="sing ...

  9. iOS 实现时间线列表效果

    之前看到美团的订单详情页面很有特色,于是决定模仿一下这个效果. 其实就是简单的 TableView 技巧,下面我们就来一步一步实现它. 画个泡泡 首先到 Sketch 里画出气泡的效果 很简单,一个圆 ...

随机推荐

  1. PS基础

    1.仿制图章工具:[小  ]大   建立一个新的图层,可以进行图片某个部分的复制,完全复制之后,还可以调整大小(ctrl+t), 颜色(ctrl+u打开色相饱和度的菜单)等. 2.修复画笔工具:与仿制 ...

  2. Convert Date between LocalDateTime

    http://blog.progs.be/542/date-to-java-time Java8 has new date and time classes to “replace” the old ...

  3. 怎样在CentOS 7.0上安装和配置VNC服务器

    VNC轻松连接远程Linux桌面 http://jingyan.baidu.com/article/6c67b1d6f1bac92786bb1e6d.html 这是一个关于怎样在你的 CentOS 7 ...

  4. git svn 简易同时使用

    这个方法适合于新的一个git 仓库.假如你使用的git 是最新版本,git本身提供了 git svn命令. 1. 进入一个空的目录,初始化一个空的git仓库: git svn init svn://x ...

  5. HTML5 乱记

    HTML5 的文档类型声明可以触发所有具备标准模式的浏览器的标准模式,包括那些对 HTML5 一无所知的浏览器,也就是说,可以在任何网页中都使用 HTML5 文档类型声明 <!DOCTYPE h ...

  6. jsp实现计算器

    JavaBean package com.itheima.domain; import java.math.BigDecimal; public class BigDecimalDemo { priv ...

  7. hadoop命令报错:权限问题

    root用户执行hadoop命令报错: [root@vmocdp125 conf]# hadoop fs -ls /user/ [INFO] 17:50:42 main [RetryInvocatio ...

  8. ios常用的一些类库

    在网上收集到的 一:第三方插件 1:基于响应式编程思想的oc 地址:https://github.com/ReactiveCocoa/ReactiveCocoa 2:hud提示框 地址:https:/ ...

  9. C# 匿名类型

    c#3.0引入匿名类型,其由编译器动态生成而非显式定义. using System;using System.Collections.Generic;using System.Linq;using S ...

  10. Java实战之03Spring-01Spring概述

    一.Spring概述 1.Spring是什么? Spring是分层的Java SE/EE应用 full-stack轻量级开源框架,以IoC(Inverse Of Control:反转控制)和AOP(A ...