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的点击事件,即每行的点击事件
四个方法的重载如下:
三,元素在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)之间,所以才需要采用下面的方式来获取点击位置
获得点击行数后就是内部判断了
效果图如下,效果还算不错
一,要使用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; } }
效果图如下,效果还算不错
相关文章推荐
- Cocos2d-x学习笔记(五)—— 常见UI界面(未完全)
- cocos2dx-3.0(13)------SpriteBatchNode与SpriteFrameCache加快渲染
- cocos2dx3.6实现打字效果
- cocos2d-x综述(源自cocos2d-x中文网)
- Cocos2D游戏之旅(四):卡牌翻转效果的实现(下)
- cocos2dx-屏幕设置
- cocos2dx-粒子特效
- cocos2dx-音乐音效
- cocos2dx-多点触控
- cocos2dx-触屏事件
- cocos2dx-33种场景切换
- cocos2dx-24种基本特效
- cocos2dx-基本动画制作
- cocos2dx-CCScrollView的制作
- 【Cocos2d入门教程二】Cocos2d-x基础篇
- cocos2dx-Action动作
- cocos2dx-cpptest的结构
- cocos2d-x CCScale9Sprite实例
- Cocos2d-x学习笔记(四)—— 内存管理
- cocos坐标详解