效果:

代码:

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. 禁用 Browser Link,在浏览器调试的时候回出现大量的get,post数据。

    VS2013新增的Browser Link功能虽然“强大”,但默认是开启的,很烦人!

  2. CentOS7安装Tomcat8.X

    安装说明 安装环境:CentOS7安装方式:源码安装软件:apache-tomcat-8.0.30.tar.gz下载地址:http://tomcat.apache.org/download-80.cg ...

  3. MSP430常见问题之工作模式和功耗类

    Q1:1,MSP430进入LP 模式后,CPU 停止运行,那么,进入中断执行退出后,由于SR的恢复,导致还处于LP 模式,是否意味着,CPU 在退出中断后立即停止了呢?2,也就是说,进入LP 模式后, ...

  4. nodejs 微信中使用file组件上传图片在某些机型上点击无反应

    看下下面的代码: <form action="/" class="file_upload" method="post" enctype ...

  5. Linux下安装MATLAB的一些注意事项

    1,下载matlab的linux版本. matlab2012a的种子文件, Matlab_Unix_2012a.torrent 我是在window机子上下载了MATLAB的Linux版本. 2,把MA ...

  6. C#下解决DrawImage画出来的Image变大了的问题

    如: private Image image= Resources.image1;//假设image1这张资源图是360×600这么大 private Graphics graphics; graph ...

  7. poj2337 欧拉路径

    poj2337 这道题昨天晚上开始做,今天才A.但是问题想透了, 发现其实没那么难 题目大意: 给你一些单词,如果一个单词的末尾字符与另一个单词首字符相同,则两个的单词可以连接.问是否可以把所有单词连 ...

  8. 12天学好C语言——记录我的C语言学习之路(Day 9)

    12天学好C语言--记录我的C语言学习之路 Day 9: 函数部分告一段落,但是我们并不是把函数完全放下,因为函数无处不在,我们今后的程序仍然会大量运用到函数 //转入指针部分的学习,了解指针是什么 ...

  9. mysql空间数据相关操作

    建表语句: CREATE TABLE ts.points ( name ) NOT NULL, location POINT NOT NULL, description ) ); 添加记录如下: IN ...

  10. OC1_类与对象

    // // main.m // OC1_类与对象 // // Created by zhangxueming on 15/6/9. // Copyright (c) 2015年 zhangxuemin ...