cocos2dx tableview的實際應用

tableview作爲一種UI是非常實用的,它可以顯示多列元素,並且可以通過滑動來即時加載元素,常用的就是遊戲中的物品欄,物品欄在各類遊戲中都佔有很重要的地位,卡牌遊戲中卡牌的整理,RPG中的物品欄等,這些都需要滑動換頁,元素點擊的要素,而tableview在功能上能夠完美的實現這個,接下來以實際的卡牌的整理界面來介紹tableview
一,要使用tableview首先需要繼承cocos2dx中tableviewdatasource和TableViewDelegate兩個類,並重載其中的四個方法
virtual TableViewCell* tableCellAtIndex(TableView *table,ssize_t idx);
//返回單元格個數,指的是行數,不是指行內總元素的個數
virtual ssize_t numberOfCellsInTableView(TableView *table);
//根據index設置單元格大小,同樣指每行的size
virtual Size tableCellSizeForIndex(TableView *tabe,ssize_t idx);
//cell中的元素顯示,即每行中要顯示的元素都是在這個函數中完成載入的
virtual void tableCellTouched(TableView *table ,TableViewCell *cell);
//cell的點擊事件,即每行的點擊事件
四個方法的重載如下:

//這裏需要使用dequeuecell來獲得cell,如果直接在內部創建cell會導致cell被重複創建,元素的顯示會變異常,需要注意僅在獲得的cell爲空的前提下才創建cell,否則只需改變
原有cell中的元素即可,
TableViewCell* CardSelectScene::tableCellAtIndex(TableView *table,ssize_t idx){
    TableViewCell *cell=table->dequeueCell();
    auto barray=Array::create();
    int index=idx*3;
    int indexfor=0;
    int length=0;
    if(table->getTag()==0){
        barray=array;
    }else if(table->getTag()==1){
        barray=sarray;
    }
    if(barray!=NULL){
     if(barray->count()-index<3){
           length=barray->count()-index;
     }else{
           length=3;
     }
     if(!cell){
        cell=new TableViewCell();
        cell->autorelease(); 
     }else{
         cell->removeAllChildren();
     }
     for(int m=0;m<length;m++){  
        Dictionary* str=((Dictionary*)array->objectAtIndex(index+m));
        custombutton *item=custombutton::createLayer(str);
        if(item!=NULL){
        item->setAnchorPoint(Point::ZERO);
        //item->setScale(0.6);
        indexfor=index+m;
        item->setTag(index+m);
        item->setPosition(Point(150*m,0));
        item->setTouchEnabled(true);
        item->setTouchMode(Touch::DispatchMode::ONE_BY_ONE);
        cell->addChild(item);
        }
    }   
    }

    return cell;
    //idx爲行號


}


    //返回單元格個數
 ssize_t CardSelectScene::numberOfCellsInTableView(TableView *table){
     if(table->getTag()==0){
    if(array->count()!=0){
       if(array->count()<=3){
         return 1;
        }else{
         return 1+array->count()/3;
      }

    }else{
        return 2;

    }
    }else if(table->getTag()==1){
        if(sarray==NULL){
            return 0;
        }else{
            if(sarray->count()!=0){
       if(sarray->count()<=3){
         return 1;
         }else{
         return 1+sarray->count()/3;
        }

       }else{
        return 2;

    }

        }

    }
 }
    //根據index設置單元格大小
 Size CardSelectScene::tableCellSizeForIndex(TableView *table,ssize_t  idx){
     return Size(434,260);
}
void CardSelectScene::tableCellTouched(TableView *table ,TableViewCell *cell){
    CCLOG("cell touched at index: %ld", cell->getIdx());



}

三,元素在cell中的點擊
如果在cell中添加的元素含有menu類的控件時,會發現tableview會無法進行拖動,這是因爲響應優先級的問題,這個問題會在之後詳細介紹,今天要介紹的是元素的點擊,因爲實際點擊時通過touch指針獲取的點擊位置是世界座標,並不是cell內部的相對座標,而通過調試會發現,cell內部的座標全是相對於該cell的相對座標,再加上cocos2dx中通過dispatcher下發各種消息時會將消息均等的發送給所有此時在tableview界面上的元素,這樣實際用getBoundingBox()來判斷是否在元素範圍內是很蛋疼的,所以這裏採用一個折中的方案,先獲得點擊的是哪個cell,不是這個cell就不管,是在該cell中再繼續判斷,獲取點擊cell的位置如下,因爲對於tableview來說其cell的offset也是相對的,並且很蛋疼的是它還是個負值,以260爲高度,個數爲15個的tableview來說,最上面的0號cell,它的位置其實是(0,-3900)~(0,-3640)之間,所以才需要採用下面的方式來獲取點擊位置

auto locationworld =touch->getLocation();
auto offset=table->getContentOffset();
auto distance=locationworld.y-offset.y;//獲得相對座標,垂直顯示時的獲取方法
auto index=maxsize-(int)(distance/260)-1;//獲取點擊的cell的index,這裏260是每行cell的高度,maxsize就是tableview總的cell個數,

獲得點擊行數後就是內部判斷了

//判斷如果點擊位置是在上部時
if(cell->getIdx()%2==0){
            if(locationworld.y>260){
                Point location=Point(locationworld.x,locationworld.y-260);
                if(this->getBoundingBox().containsPoint(location)){
                    log("m_power is %d",this->m_power);
                    return true;
                }else{
                    return false;
                }
            }else{
                Point location=Point(locationworld.x,locationworld.y);
                if(this->getBoundingBox().containsPoint(location)){
                    log("m_power is %d",this->m_power);
                    return true;
                }else{
                    return false;
                }
            }
        //判斷是在下部時
        }else if(cell->getIdx()%2==1){
             Point location=Point(locationworld.x,locationworld.y);
            if(this->getBoundingBox().containsPoint(location)){
                    log("m_power is %d",this->m_power);
                    return true;
             }else{
                    return false;
             }
        }

效果圖如下,效果還算不錯
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章