您的位置:首页 > 移动开发 > Cocos引擎

cocos2dx tableview的实际应用

2015-08-09 00:36 561 查看
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;
}
}


效果图如下,效果还算不错

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: