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;
             }
        }

效果图如下,效果还算不错
cocos2dx tableview的实际应用_第1张图片

你可能感兴趣的:(cocos2dx)