zoukankan      html  css  js  c++  java
  • 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容器
    };
    View Code

    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);
        
    }
    View Code

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

            //创建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);
    View Code
  • 相关阅读:
    RESTful API 设计原则
    c#的逆变和协变
    Java内部类之间的闭包和回调详解
    java的内部类
    抓包工具
    HashMap与HashTable的区别
    Java 语法清单
    Java面试问题列表
    bootstrap table api
    c# CacheManager 缓存管理
  • 原文地址:https://www.cnblogs.com/gamesky/p/5431469.html
Copyright © 2011-2022 走看看