[cocos2dx]tableview的使用

邹星火
2023-12-01

TableView,ListView都继承自ScrollView
ListView中的每个单元称为item,TableView的每个单元称为cell,如果分别创建20个单元,但每次只能显示5个单元。当ListView创建的时候,会直接创建20个item;而TableView只会创建5个cell,然后在队列中反复利用。

1.首先要知道头文件 和 命名空间

#include "cocos2d.h"
#include "cocos-ext.h"
 
USING_NS_CC;
USING_NS_CC_EXT;


class HelloWorld : public Layer,TableViewDataSource,TableViewDelegate
{
};

2.必备的函数

/* 必须实现的函数 */
// 当滑动tableview时触发该方法 参数为当前的tableview对象
virtual void scrollViewDidScroll(ScrollView* view) {};
// 当tableview被放大或缩小时触发该方法  参数为当前tableview对象
virtual void scrollViewDidZoom(ScrollView* view) {}
// 当cell被点击时调用该方法 参数为当前的tableview对象与被点击的cell对象
virtual void tableCellTouched(TableView* table, TableViewCell* cell);
// 设置tableview的Cell大小
virtual Size tableCellSizeForIndex(TableView *table, ssize_t idx);
// 获取编号为idx的cell
virtual TableViewCell* tableCellAtIndex(TableView *table, ssize_t idx);
// 设置tableview中cell的个数
virtual ssize_t numberOfCellsInTableView(TableView *table);

UIMainPage文件

//==============UIMainPage头文件================
class UIMainPage : public Layer
,public TableViewDataSource
,public TableViewDelegate
,public CBaseKeyListener
{
public:
    CREATE_FUNC(UIMainPage);
    
    virtual void onEnter() override;
    virtual void onExit() override;
    virtual bool init() override;
    virtual bool OnBaseKeyBack() override;
    
    virtual Size tableCellSizeForIndex(TableView *table, ssize_t idx) override;
    virtual TableViewCell* tableCellAtIndex(TableView *table, ssize_t idx) override;
    virtual ssize_t numberOfCellsInTableView(TableView *table) override;
    
    virtual void scrollViewDidScroll(cocos2d::extension::ScrollView* view) override;
    virtual void scrollViewDidZoom(cocos2d::extension::ScrollView* view) override;
    
    virtual void tableCellTouched(TableView* table, TableViewCell* cell) override;
//    virtual void tableCellHighlight(TableView* table, TableViewCell* cell) override;
//    virtual void tableCellUnhighlight(TableView* table, TableViewCell* cell) override;
//    virtual void tableCellWillRecycle(TableView* table, TableViewCell* cell) override;
private:
    UIMainPage();
    ~UIMainPage();
    // ...
};




//==============UIMainPage cpp文件================

void UIMainPage::initTableView()
{
    //创建tableview
    auto size = mapWidget["PanelBook"]->getContentSize();
    auto tableview = mTableView = TableView::create(this, size);
    tableview->setDirection(cocos2d::extension::ScrollView::Direction::VERTICAL);
    tableview->setDelegate(this);
    tableview->setVerticalFillOrder(TableView::VerticalFillOrder::TOP_DOWN);
    mapWidget["PanelBook"]->addChild(tableview);
    mItemSize = Size(size.width,size.height/3.5);//每个tableCell的大小
    
    //请求数据
    if(HomePageManager::getInstance()->getHomePageModel()->getAllWeekBookListCount() == 0){
        isGoToCurCell = true;
        isReqLoading = true;
        HomePageManager::getInstance()->reqHomePageBookList(true);
    }
    else{
        reflashData();
    }
}

Size UIMainPage::tableCellSizeForIndex(TableView *table, ssize_t idx)
{
    return mItemSize;
}
TableViewCell* UIMainPage::tableCellAtIndex(TableView *table, ssize_t idx)
{
    CCLOG("UIMainPage-----tableCellAtIndex index: %d", (int)idx);
    TableViewCell* cell = table->dequeueCell();
    if(!cell){
        cell = UIMainBookCell::create();
        dynamic_cast<UIMainBookCell*>(cell)->initUI();
    }
    auto data = HomePageManager::getInstance()->getHomePageModel()->getOneWeekBookListByIndex((int)idx);
    bool flag = HomePageManager::getInstance()->getHomePageModel()->isCurWeekID(data->_WeekID);
    dynamic_cast<UIMainBookCell*>(cell)->updateCell(data,flag);
    
    return cell;
}
ssize_t UIMainPage::numberOfCellsInTableView(TableView *table)
{
    int num = HomePageManager::getInstance()->getHomePageModel()->getAllWeekBookListCount();
    return num;
}

void UIMainPage::scrollViewDidScroll(cocos2d::extension::ScrollView* view)
{
    CCLOG("UIMainPage-----scrollViewDidScroll#########   %f  *****ContentSize***** %f  *****ViewSize***** %f"
          ,view->getContentOffset().y
          ,view->getContentSize().height
          ,view->getViewSize().height);
    if(isReqLoading || isGoToCurCell){
        CCLOG("UIMainPage-----scrollViewDidScroll--isReqLoading");
        return;
    }
    if(view->getContentOffset().y > 80){
        //请求数据
        CCLOG("UIMainPage-----scrollViewDidScroll--up");

        bool acc = HomePageManager::getInstance()->reqHomePageBookList(true);
        if(acc == false){
            TipManager::getInstance()->showTipWithString("之后数据已全部加载");
        }else{
            isReqLoading = true;
        }
    }else{
        float dis = view->getContentSize().height - view->getViewSize().height;
        if(std::abs(view->getContentOffset().y) - std::abs(dis) > 80){
            CCLOG("UIMainPage-----scrollViewDidScroll--down");
            
            bool acc = HomePageManager::getInstance()->reqHomePageBookList(false);
            if(acc == false){
                TipManager::getInstance()->showTipWithString("之前数据已全部加载");
            }else{
                isReqLoading = true;
            }
        }
    }
}
void UIMainPage::scrollViewDidZoom(cocos2d::extension::ScrollView* view)
{
    
}
void UIMainPage::tableCellTouched(TableView* table, TableViewCell* cell)
{
    CCLOG("UIMainPage-----cell touched at index: %ld", cell->getIdx());
}

//接收到数据
void UIMainPage::onRevMsgDoHandle(Ref* ref)
{
    MsgParam* param = (MsgParam*)ref;
    if(param->getIsResOK()){
        CCLOG("UIMainPage::onRevMsgDoHandle::===-OK-====");
        if(isGoToCurCell){
            int index = HomePageManager::getInstance()->getHomePageModel()->getIndexByWeekID();
            CCLOG("UIMainPage::onRevMsgDoHandle::===--====%d",index);
            if(index > 2){//没找到-1,第0,1 不需要定位
                mTableView->reloadData();
                int num = HomePageManager::getInstance()->getHomePageModel()->getAllWeekBookListCount();
                if(num - index == 1){//当要定位到最后一个时,位置会偏空,则给定位到倒数第2个
                    index = index - 1;
                }
                goToCell(index);
            }else{
                reflashData();
            }
            isGoToCurCell = false;
        }else{
            reflashData();
        }
    }else{
    }
    isReqLoading = false;
}

void UIMainPage::reflashData()
{
    Vec2 oldOff = mTableView->getContentOffset();
    Size oldSize = mTableView->getContentSize();
    mTableView->reloadData();
    Size newSize = mTableView->getContentSize();
    oldOff.y -= newSize.height - oldSize.height;
    mTableView->setContentOffset(oldOff);
}

//跳转到指定的Cell
void UIMainPage::goToCell(int index)
{
    CCLOG("UIMainPage-----goToCell:ss--222--- %d", index);
    Vec2 offset = mTableView->getContentOffset();
    int sum = (int)this->numberOfCellsInTableView(mTableView);
    int idx = sum - index - 1;
    offset.y = -((idx - 1) * mItemSize.height);
    mTableView->setContentOffset(offset,false);
}

UIMainBookCell文件

//==============UIMainPage头文件================
class UIMainBookCell : public cocos2d::extension::TableViewCell
{
public:
    CREATE_FUNC(UIMainBookCell);
    virtual void onEnter() override;
    virtual void onExit() override;
    virtual bool init() override;

    void initUI();
    void updateCell(EntOneWeekBookList* entBookList,bool isCurWeek);
private:
    void touchBookEvent(Ref *pSender, Widget::TouchEventType eventType);
    void doClickBookHandle(void* data);
private:
    std::unordered_map<string, Widget*> mapWidget;
    float maxDistance;
    Vec2 touchBeginPos;
};


//==============UIMainBookCell cpp文件================
void UIMainBookCell::updateCell(EntOneWeekBookList* entBookList,bool isCurWeek)
{
    if(!entBookList){
        CCLOG("xuebang--error,void UIMainBookCell::updateCell(EntOneWeekBookList* entBookList) entBookList==null");
        return;
    }
    
    mapWidget["lvBook"]->removeAllChildren();
    
    if(isCurWeek){
        mapWidget["imgBG"]->setColor(Color3B(255,192,203));
    }else{
        mapWidget["imgBG"]->setColor(Color3B::WHITE);
    }
    ((Text*)mapWidget["txtTitle"])->setString(entBookList->_Title);
    ((Text*)mapWidget["txtDateTime"])->setString(entBookList->_DateTime);
    for(auto book : entBookList->vecBook){
        auto item = (Layout*)mapWidget["panel_book"]->clone();
        ImageView* imgBook = (ImageView*)item->getChildByName("img_book");
        imgBook->setTouchEnabled(true);
        imgBook->setSwallowTouches(false);
        imgBook->addTouchEventListener(CC_CALLBACK_2(UIMainBookCell::touchBookEvent, this));
        imgBook->getChildByName("img_read")->setVisible(book->_IsReadFlag);
        
        ImageView* img_level = (ImageView*)imgBook->getChildByName("img_level");
        if (book->_BookLevel.length() >= 1) {
            img_level->setVisible(true);
            img_level->loadTexture(StringUtils::format("Image/SubImg/Commom/BookItem/main_letter_%s.png", book->_BookLevel.c_str()), Widget::TextureResType::PLIST);
        } else {
            img_level->setVisible(false);
        }
//        book->_CoverUrl = "http://db-app-source.dubaner.com/resource/pdf_img/test/NOAJ-004/NOAJ-004111.png";
        DownImg::getInstance()->DownFile(book->_CoverUrl.c_str(), imgBook);//, "bookDefault.png"
        imgBook->setUserData(&book->_BookID);
        ((ListView*)mapWidget["lvBook"])->pushBackCustomItem(item);
    }
    if(entBookList->vecBook.size() > 3){
        ((ListView*)mapWidget["lvBook"])->setScrollBarEnabled(true);
    }else{
        ((ListView*)mapWidget["lvBook"])->setScrollBarEnabled(false);
    }
}

void UIMainBookCell::touchBookEvent(Ref *pSender, Widget::TouchEventType eventType)
{
    //ListView滑动小于10像素时表示点击事件,滑动时不会触发点击事件
    ImageView* cb = (ImageView*)pSender;
    if (eventType == Widget::TouchEventType::BEGAN) {
        touchBeginPos = cb->convertToWorldSpace(Vec2(0, 0));
        maxDistance = 0;
        CCLOG("BEGAN");
    } else if (eventType == Widget::TouchEventType::MOVED) {
        Vec2 newPos = cb->convertToWorldSpace(Vec2(0, 0));
        float dis = newPos.distance(touchBeginPos);
        if(dis > maxDistance){
            maxDistance = dis;
        }
        log("MOVED--%f",dis);
    } else if (eventType == Widget::TouchEventType::ENDED) {
        if (maxDistance < 10) {
            doClickBookHandle(cb->getUserData());
        }
        CCLOG("ENDED");
    } else if (eventType == Widget::TouchEventType::CANCELED) {
        CCLOG("CANCELED");
    }
}

void UIMainBookCell::doClickBookHandle(void* data)
{
    string* id = (string*)data;
    string bookID = *id;
    CCLOG("UIMainBookCell::doClickBookHandle----bookID=%s",bookID.c_str());
    
    Reador::getInstance()->setCurrentBook(bookID);
    SceneManager::getInstance()->setGameState(eStateBook);
}

 

 类似资料: