zoukankan      html  css  js  c++  java
  • CCScrollView/CCTableView(CCTableViewDelegate CCTableViewDataSource CCTableView-滑动列表-游戏中大量使用 非常重要的一个类)

    tableview 

    scrollViewDidScroll函数中有一段   ----  即---滑动tableview时触发的函数 : 会将全部显示的cell又一次刷新(刷新函数中调用了自己定义的tableCellAtIndex

    //////

        for (unsigned int i=startIdx; i <= endIdx; i++)

        {

            //if ([m_pIndices containsIndex:i])

            if (m_pIndices->find(i) != m_pIndices->end())

            {

                continue;

            }

            this->updateCellAtIndex(i);

        }

    ////////


    updateCellAtIndex(i);中有一段

    ////

    cell = m_pDataSource->tableCellAtIndex(this, idx);

    ///

    使用样例

    classListViewLayer : 
    publiccocos2d::CCLayer, 
    publiccocos2d::extension::CCTableViewDataSource, (关于cell的数据 包含4个虚函数:tableCellSizeForIndexcellSizeForTabletableCellAtIndexnumberOfCellsInTableView
    publiccocos2d::extension::CCTableViewDelegate(继承自CCScrollViewDelegate 又添加了4个触摸回调 包含4个虚函数:tableCellTouchedtableCellHighlighttableCellUnhighlighttableCellWillRecycle)
    {
    public:
        virtualboolinit(); 
    ///////
    boolListViewLayer::init()
    {
        boolbRet = false;
        do
        {
            CC_BREAK_IF( !CCLayer::init() );
     
            CCTableView* pTableView = CCTableView::create(this, CCSizeMake(960, 640));
            pTableView->setDirection(kCCScrollViewDirectionVertical);
            pTableView->setPosition(CCPointZero);
            pTableView->setDelegate(this);
            pTableView->setVerticalFillOrder(kCCTableViewFillTopDown);
            this->addChild(pTableView);
            pTableView->reloadData();
     
            bRet = true;
        }while(0);
     
        returnbRet;
    }
    //////

     
        virtualvoidscrollViewDidScroll(cocos2d::extension::CCScrollView* view);
     
        virtualvoidscrollViewDidZoom(cocos2d::extension::CCScrollView* view);
     
        //处理触摸事件。能够计算点击的是哪一个子项
        virtualvoidtableCellTouched(cocos2d::extension::CCTableView* table, cocos2d::extension::CCTableViewCell* cell);
    ////// 
    voidListViewLayer::tableCellTouched(CCTableView* table, CCTableViewCell* cell)
    {
        CCLog("cell touched at index: %i", cell->getIdx());
    }
    /////
    //每一项的宽度和高度必须重写的一个虚函数
        virtualcocos2d::CCSize cellSizeForTable(cocos2d::extension::CCTableView *table);
        //生成列表每一项的内容 必须重写的一个虚函数
        virtualcocos2d::extension::CCTableViewCell* tableCellAtIndex(cocos2d::extension::CCTableView *table, unsignedintidx);
    ////////
     
    CCTableViewCell* ListViewLayer::tableCellAtIndex(CCTableView *table, unsigned intidx)
    {
        CCString *pString = CCString::createWithFormat("%d", idx);
        CCTableViewCell *pCell = table->dequeueCell(); //得到一个将要离队(释放)的cell
        if(!pCell) { //假设释放池中没有 就自己创建一个 节约内存
            pCell = newCCTableViewCell();
            pCell->autorelease();
            CCSprite *pSprite = CCSprite::create("listitem.png");
            pSprite->setAnchorPoint(CCPointZero);
            pSprite->setPosition(CCPointZero);
            pCell->addChild(pSprite);
     
            CCLabelTTF *pLabel = CCLabelTTF::create(pString->getCString(), "Arial", 20.0);
            pLabel->setPosition(CCPointZero);
            pLabel->setAnchorPoint(CCPointZero);
            pLabel->setTag(123);
            pCell->addChild(pLabel);
        }
        else
        {
            CCLabelTTF *pLabel = (CCLabelTTF*)pCell->getChildByTag(123);
            pLabel->setString(pString->getCString());
        }
     
        returnpCell;
    }
    ////////
        //一共多少项必须重写的一个虚函数
        virtualunsignedintnumberOfCellsInTableView(cocos2d::extension::CCTableView *table);
     /////
     
    unsignedintListViewLayer::numberOfCellsInTableView(CCTableView *table)
    {
        return20;
    }
    ///////
        CREATE_FUNC(ListViewLayer);
    };
     

    首先须要创建CCTableView。设置它的显示区域和显示方向,这里使用了纵向。设置每一个子项的宽度和高度,子项的数量以及每一个子项相应的内容。每一个子项是一个CCTableViewCell,这里进行了优化。复用了子项对象。
    以下是效果图:






    #ifndef __CCTABLEVIEW_H__

    #define __CCTABLEVIEW_H__


    #include "CCScrollView.h"

    #include "CCTableViewCell.h"


    #include <set>

    #include <vector>


    NS_CC_EXT_BEGIN


    class CCTableView;

    class CCArrayForObjectSorting;


    typedef enum {

        kCCTableViewFillTopDown,  //靠顶端

        kCCTableViewFillBottomUp

    } CCTableViewVerticalFillOrder;  //fill 装满 填充


    /**

     * Sole(唯一的) purpose(目的 用途) of this delegate(代表) is to single touch(单点触摸) event in this version.//这个版本号仅支持单点触摸

     */

    class CCTableViewDelegate : public CCScrollViewDelegate

    {

    public:

        /**

         * Delegate to respond(做出反应) touch event

         */

        virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell) = 0;


        /**

         * Delegate to respond a table cell press event.

         */

        virtual void tableCellHighlight(CCTableView* table, CCTableViewCell* cell){};//Highlight 突出 加亮  点击事件


        /**

         * Delegate to respond a table cell release event 

         */

        virtual void tableCellUnhighlight(CCTableView* table, CCTableViewCell* cell){};//松开事件


        /**

         * Delegate called when the cell is about to(即将) be recycled. Immediately

         * after this call the cell will be removed from the scene graph and

         * recycled.

         */

        virtual void tableCellWillRecycle(CCTableView* table, CCTableViewCell* cell){};//cell即将回收事件


    };



    /**

     * Data source that governs(治理) table backend(后端) data.

     */

    class CCTableViewDataSource

    {

    public:

        virtual ~CCTableViewDataSource() {}


        /**

         * cell size for a given index

         *

         * @param idx the index of a cell to get a size

         * @return size of a cell at given index

         */

        virtual CCSize tableCellSizeForIndex(CCTableView *table, unsigned int idx) {   //得到指定ins的cell的size

            return cellSizeForTable(table);

        };

        /**

         * cell height for a given table.

         */

        virtual CCSize cellSizeForTable(CCTableView *table) {  //cell的size

            return CCSizeZero;

        };

        /**

         * a cell instance at a given index

         *

         * @param idx index to search for a cell

         * @return cell found at idx

         */

        virtual CCTableViewCell* tableCellAtIndex(CCTableView *table, unsigned int idx) = 0;  //得到指定idx的 cell

        /**

         * Returns number of cells in a given table view.

         */

        virtual unsigned int numberOfCellsInTableView(CCTableView *table) = 0;//得到cell数量


    };



    /**

     * UITableView counterpart(副本) for cocos2d for iphone.

     * this is a very basic, minimal(最低的) implementation(实现) to bring UITableView-like component into(作为组件插入) cocos2d world.

     */

    class CCTableView : public CCScrollView, public CCScrollViewDelegate

    {

    public:

        CCTableView();

        virtual ~CCTableView();


        /**

         * An initialized(初始的) table view object

         */

        static CCTableView* create(CCTableViewDataSource* dataSource, CCSize size); 

        /**

         * An initialized table view object

         */

        static CCTableView*create(CCTableViewDataSource* dataSource, CCSize size, CCNode *container);

    //////

    CCTableView* CCTableView::create(CCTableViewDataSource* dataSource, CCSize size, CCNode *container)

    {

        CCTableView *table = new CCTableView();

        table->initWithViewSize(size, container);

        table->autorelease();

        table->setDataSource(dataSource);

        table->_updateCellPositions();

        table->_updateContentSize();

        return table;

    }

    ///////


        CCTableViewDataSource* getDataSource() { return m_pDataSource; }

        void setDataSource(CCTableViewDataSource* source) { m_pDataSource = source; }


        CCTableViewDelegate* getDelegate() { return m_pTableViewDelegate; }

        void setDelegate(CCTableViewDelegate* pDelegate) { m_pTableViewDelegate = pDelegate; }


        /**

         * determines how cell is ordered and filled in the view. //确定cell在tableview中怎样排列

         */

        void setVerticalFillOrder(CCTableViewVerticalFillOrder order);

        CCTableViewVerticalFillOrder getVerticalFillOrder();



        boolinitWithViewSize(CCSize size, CCNode* container = NULL);

    ////////

    bool CCTableView::initWithViewSize(CCSize size, CCNode* container/* = NULL*/)

    {

        if (CCScrollView::initWithViewSize(size,container))

        {

            m_pCellsUsed      = new CCArrayForObjectSorting();

            m_pCellsFreed     = new CCArrayForObjectSorting();

            m_pIndices        = new std::set<unsigned int>();

            m_eVordering      = kCCTableViewFillBottomUp;

            this->setDirection(kCCScrollViewDirectionVertical);

            CCScrollView::setDelegate(this);

            return true;

        }

        return false;

    }

    ////////

        /**

         * Updates the content of the cell at a given index.

         */

        voidupdateCellAtIndex(unsigned int idx);//更新cell

    ////////////////

    void CCTableView::updateCellAtIndex(unsigned int idx)

    {

        if (idx == CC_INVALID_INDEX)

        {

            return;

        }

        unsigned int uCountOfItems = m_pDataSource->numberOfCellsInTableView(this);

        if (0 == uCountOfItems || idx > uCountOfItems-1)

        {

            return;

        }

        CCTableViewCell* cell = this->cellAtIndex(idx);

        if (cell)

        {

            this->_moveCellOutOfSight(cell);

        }

        cell = m_pDataSource->tableCellAtIndex(this, idx);

        this->_setIndexForCell(idx, cell);

        this->_addCellIfNecessary(cell);

    }

    //////////////


        void insertCellAtIndex(unsigned int idx);//插入新的cell 


        void removeCellAtIndex(unsigned int idx);//移除cell


        void reloadData();//又一次下载datasource view 将更新

        /**

         * Dequeues a free cell if available. nil if not.

         */

        CCTableViewCell *dequeueCell();//得到一个将要离队(释放)的cell

    ///////

    CCTableViewCell *CCTableView::dequeueCell()

    {

        CCTableViewCell *cell;

        if (m_pCellsFreed->count() == 0) {

            cell = NULL;   //假设释放池中没有就返回0

        } else {           //假设释放池中有就返回第一个

            cell = (CCTableViewCell*)m_pCellsFreed->objectAtIndex(0);

            cell->retain();

            m_pCellsFreed->removeObjectAtIndex(0);

            cell->autorelease();

        }

        return cell;

    }

    //////////



        /**

         * Returns an existing(眼下的) cell at a given index. Returns nil if a cell is nonexistent at the moment of query.

         */

        CCTableViewCell *cellAtIndex(unsigned int idx);//按给定的idx 返回一个cell

    ////////

    CCTableViewCell *CCTableView::cellAtIndex(unsigned int idx)

    {

        CCTableViewCell *found = NULL;

        if (m_pIndices->find(idx) != m_pIndices->end())

        {

            found = (CCTableViewCell *)m_pCellsUsed->objectWithObjectID(idx);

        }

        return found;

    }

    ///////////


        virtual voidscrollViewDidScroll(CCScrollView* view);

    //////////

    void CCTableView::scrollViewDidScroll(CCScrollView* view)

    {

        unsigned int uCountOfItems = m_pDataSource->numberOfCellsInTableView(this);

        if (0 == uCountOfItems)

        {

            return;

        }

        if(m_pTableViewDelegate != NULL) {

            m_pTableViewDelegate->scrollViewDidScroll(this);

        }

        unsigned int startIdx = 0, endIdx = 0, idx = 0, maxIdx = 0;

        CCPoint offset = ccpMult(this->getContentOffset(), -1);

        maxIdx = MAX(uCountOfItems-1, 0);

        if (m_eVordering == kCCTableViewFillTopDown)

        {

            offset.y = offset.y + m_tViewSize.height/this->getContainer()->getScaleY();

        }

        startIdx = this->_indexFromOffset(offset);

    if (startIdx == CC_INVALID_INDEX)

    {

    startIdx = uCountOfItems - 1;

    }

        if (m_eVordering == kCCTableViewFillTopDown)

        {

            offset.y -= m_tViewSize.height/this->getContainer()->getScaleY();

        }

        else

        {

            offset.y += m_tViewSize.height/this->getContainer()->getScaleY();

        }

        offset.x += m_tViewSize.width/this->getContainer()->getScaleX();

        endIdx   = this->_indexFromOffset(offset);

        if (endIdx == CC_INVALID_INDEX)

    {

    endIdx = uCountOfItems - 1;

    }

    #if 0 // For Testing.

        CCObject* pObj;

        int i = 0;

        CCARRAY_FOREACH(m_pCellsUsed, pObj)

        {

            CCTableViewCell* pCell = (CCTableViewCell*)pObj;

            CCLog("cells Used index %d, value = %d", i, pCell->getIdx());

            i++;

        }

        CCLog("---------------------------------------");

        i = 0;

        CCARRAY_FOREACH(m_pCellsFreed, pObj)

        {

            CCTableViewCell* pCell = (CCTableViewCell*)pObj;

            CCLog("cells freed index %d, value = %d", i, pCell->getIdx());

            i++;

        }

        CCLog("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

    #endif

        if (m_pCellsUsed->count() > 0)

        {

            CCTableViewCell* cell = (CCTableViewCell*)m_pCellsUsed->objectAtIndex(0);

            idx = cell->getIdx();

            while(idx <startIdx)

            {

                this->_moveCellOutOfSight(cell);

                if (m_pCellsUsed->count() > 0)

                {

                    cell = (CCTableViewCell*)m_pCellsUsed->objectAtIndex(0);

                    idx = cell->getIdx();

                }

                else

                {

                    break;

                }

            }

        }

        if (m_pCellsUsed->count() > 0)

        {

            CCTableViewCell *cell = (CCTableViewCell*)m_pCellsUsed->lastObject();

            idx = cell->getIdx();

            while(idx <= maxIdx && idx > endIdx)

            {

                this->_moveCellOutOfSight(cell);

                if (m_pCellsUsed->count() > 0)

                {

                    cell = (CCTableViewCell*)m_pCellsUsed->lastObject();

                    idx = cell->getIdx();

                }

                else

                {

                    break;

                }

            }

        }

        for (unsigned int i=startIdx; i <= endIdx; i++)

        {

            //if ([m_pIndices containsIndex:i])

            if (m_pIndices->find(i) != m_pIndices->end())

            {

                continue;

            }

            this->updateCellAtIndex(i);

        }

    }

    //////////

        virtual void scrollViewDidZoom(CCScrollView* view) {}


        virtual bool ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent);

        virtual void ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent);

        virtual void ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent);

        virtual void ccTouchCancelled(CCTouch *pTouch, CCEvent *pEvent);


    protected:


        CCTableViewCell *m_pTouchedCell;//当前触摸的cell


        CCTableViewVerticalFillOrder m_eVordering;//fill 模式


        /**

         * index set to query the indexes of the cells used.

         */

        std::set<unsigned int>* m_pIndices;//保存cell idx的set


        /**

         * vector with all cell positions

         */

        std::vector<float> m_vCellsPositions;//保存cell position的vector

        //NSMutableIndexSet *indices_;

        /**

         * cells that are currently in the table

         */

        CCArrayForObjectSorting* m_pCellsUsed;// table中当前全部cell

        /**

         * free list of cells

         */

        CCArrayForObjectSorting* m_pCellsFreed;///

        /**

         * weak link to the data source object

         */

        CCTableViewDataSource* m_pDataSource;////

        /**

         * weak link to the delegate object

         */

        CCTableViewDelegate* m_pTableViewDelegate;////


    CCScrollViewDirection m_eOldDirection;////


        int __indexFromOffset(CCPoint offset);//依据偏移量得到idx

        unsigned int _indexFromOffset(CCPoint offset);

        CCPoint __offsetFromIndex(unsigned int index);//依据idx得到偏移量

        CCPoint _offsetFromIndex(unsigned int index);


        void _moveCellOutOfSight(CCTableViewCell *cell);////

        void _setIndexForCell(unsigned int index, CCTableViewCell *cell);

        void _addCellIfNecessary(CCTableViewCell * cell);///Necessary 必要的


        void_updateCellPositions();//更新cell位置

    ///////

    void CCTableView::_updateCellPositions() {

        int cellsCount = m_pDataSource->numberOfCellsInTableView(this);

        m_vCellsPositions.resize(cellsCount + 1, 0.0);

        if (cellsCount > 0)

        {

            float currentPos = 0;

            CCSize cellSize;

            for (int i=0; i < cellsCount; i++)

            {

                m_vCellsPositions[i] = currentPos;

                cellSize = m_pDataSource->tableCellSizeForIndex(this, i);

                switch (this->getDirection())

                {

                    case kCCScrollViewDirectionHorizontal:

                        currentPos += cellSize.width;

                        break;

                    default:

                        currentPos += cellSize.height;

                        break;

                }

            }

            m_vCellsPositions[cellsCount] = currentPos;//1 extra value allows us to get right/bottom of the last cell

        }

    }

    ////////

    public:

        void_updateContentSize();//更新table尺寸

    /////////

    void CCTableView::_updateContentSize()

    {

        CCSize size = CCSizeZero;

        unsigned int cellsCount = m_pDataSource->numberOfCellsInTableView(this);

        if (cellsCount > 0)

        {

            float maxPosition = m_vCellsPositions[cellsCount];

            switch (this->getDirection())

            {

                case kCCScrollViewDirectionHorizontal:

                    size = CCSizeMake(maxPosition, m_tViewSize.height);

                    break;

                default:

                    size = CCSizeMake(m_tViewSize.width, maxPosition);

                    break;

            }

        }

        this->setContentSize(size);

    if (m_eOldDirection != m_eDirection)

    {

    if (m_eDirection == kCCScrollViewDirectionHorizontal)

    {

    this->setContentOffset(ccp(0,0));

    }

    else

    {

    this->setContentOffset(ccp(0,this->minContainerOffset().y));

    }

    m_eOldDirection = m_eDirection;

    }

    }

    /////////


    };



    NS_CC_EXT_END


    #endif /* __CCTABLEVIEW_H__ */


  • 相关阅读:
    RSA加密
    各种正则
    用Fragment制作的Tab页面产生的UI重叠问题
    Android源码下载
    Android Studio使用百度地图问题总结
    Android获取网络类型
    Android Studio类中实现Serializable自动生成serialVersionUID
    【Android开发】如何设计开发一款Android App
    UIViewController生命周期
    微信支付开发经验分享
  • 原文地址:https://www.cnblogs.com/bhlsheji/p/5367050.html
Copyright © 2011-2022 走看看