【唠叨】

关于CCTableView的知识,网上很多大牛都写得很详细了,我也是看他们的博客进行学习的。所以在这里我只讲讲个人的学习心得,以及对CCTableView使用方法的总结。

注:因为大牛讲得都太详细了,所以本节中有些知识的介绍可能摘自各位大牛的博客。


【致谢】

http://www.zaojiahua.com/cctableview.html

http://blog.csdn.net/u012945598/article/details/20901645



【Demo下载】

https://github.com/shahdza/Cocos_LearningTest/tree/master/demo_%E5%88%97%E8%A1%A8%E8%A7%86%E5%9B%BECCTableView


【3.x】

(1)去掉 “CC”

(2)TableViewCell 中:

>unsigned int getIdx() 返回类型改为 ssize_t(类型为 long)

(3)TableViewDataSource 中:

>unsigned int idx 类型改为 ssize_t(类型为 long)

(4)TableView 中:

(A)排列方向:setDirection()

>CCScrollViewDirection 改为强枚举ScrollView::Direction

//HORIZONTAL//只能横向滚动VERTICAL//只能纵向滚动。默认方式//

(B)排列方式:setVerticalFillOrder()

>CCTableViewVerticalFillOrder 改为强枚举 TableView::VerticalFillOrder

//TOP_DOWN//从小到大排列,即idx从小到大。0123BOTTOM_UP//从大到小排列,即idx从大到小。3210。默认方式//

(5)其他变化不大。




【CCTableView】

CCTableView继承于CCScrollView,所以它具备了能够触摸滑动的功能,CCTabelView就像是一个大容器,内部由若干个CCTableViewCell单元项组成。

学习过CCScrollView之后,大家应该能够很好的理解CCTableView是如何操作的吧?实际上就是在CCScrollView的基础上,增加了对视图的容器container中的子节点对象的管理相关操作,即每个对象都是一个列表项CCTableViewCell。

如果还未学过滚动视图CCScrollView,直接看列表视图CCTableView可能会比较吃力,所以务必先掌握CCScrollView的用法。

在使用CCTableView的过程中会涉及到四个类。

(1)列表单元项 CCTableViewCell

(2)列表数据处理CCTableViewDataSource

(3)列表事件委托代理CCTableViewDelegate

(4)列表视图 CCTableView


1、CCTableViewCell

CCTableViewCell是CCTableView的单元项cell的数据类型,它继承于节点类CCNode,并且每一项cell都含有一个唯一的标识符,允许TableView通过不同的index来更新TableviewCell。

如果说视图的容器container是一个大容器的话,那么CCTableViewCell相当于是一个小容器。container放的都是每一项cell,而cell放的就是每一项的数据信息。什么CCLabel、CCSprite、CCMenu全都可以放在cell上面。

常用操作如下:

//classCCTableViewCell:publicCCNode,publicCCSortableObject{//设置cell的唯一标示符idxvoidsetIdx(unsignedintuIdx);unsignedintgetIdx();};//


2、CCTableViewDataSource

CCTableViewDataSource是非常重要的一个类,CCTableView的数据相关的处理都与该类有关。

这个必须由CCTableView所在的CCLayer图层继承,并且必须要继承如下四个虚构函数。

以下四个虚构函数都是空实现,所以必须继承和实现相关代码。

其中:

(1)cellSizeForTable()为设置每项cell的尺寸大小,即每项的大小都一样。

(2)tableCellSizeForIndex()则是根据idx来设置尺寸大小,每项大小可以不一样。

这两个函数需要选择其中一个来继承和实现。

//classCCTableViewDataSource{//设置每项cell的尺寸大小virtualCCSizecellSizeForTable(CCTableView*table);//根据idx来设置每项cell的尺寸大小virtualCCSizetableCellSizeForIndex(CCTableView*table,unsignedintidx);//获取编号为idx的cell//若还未生成idx的cell,那么就创建该项cell的内容virtualCCTableViewCell*tableCellAtIndex(CCTableView*table,unsignedintidx)=0;//列表中一共多少项cellvirtualunsignedintnumberOfCellsInTableView(CCTableView*table)=0;};//


3、CCTableViewDelegate

CCTableViewDelegate为列表视图的事件委托代理类,它继承于CCScrollViewDelegate。

这个也是必须由CCTableView所在的CCLayer图层继承,并且必须要继承如下三个虚构函数。

//classCCTableViewDelegate:publicCCScrollViewDelegate{//当cell被点击时的回调函数,用于处理被触摸的cell数据virtualvoidtableCellTouched(CCTableView*table,CCTableViewCell*cell)=0;//继承于CCScrollViewvirtualvoidscrollViewDidScroll(cocos2d::extension::CCScrollView*view){}//滚动时回调函数virtualvoidscrollViewDidZoom(cocos2d::extension::CCScrollView*view){}//放缩时回调函数};//


4、CCTableView

CCTableView中的cell是可以重用的。比如我们需要在一个CCTableView中创建10个cell,而可视区域只能够显示5个cell。我们在对cell初始化的时候,只会创建5个cell对象,也就是只做了5次 cell = new CCTableviewCell(),这是因为在talbieview中存在一个重用队列,在开始的时候,这个重用队列中是没有任何东西的,每当你滑动tableview直到一个cell被滑到了不可见的区域,这个cell就会被加入到重用队列中,然后当有一个新的cell需要被显示出来时,我们就会使用table->dequeueCell()方法,在重用队列中获取一个cell,这样的话就避免了创建一个新的cell并为它开辟内存空间。

//classCCTableView:publicCCScrollView,publicCCScrollViewDelegate{/***2种创建*///dataSource:一般为this//size:列表视图的可视区域的尺寸大小//container:自定义CCLayer容器。一般不推荐使用自定义容器staticCCTableView*create(CCTableViewDataSource*dataSource,CCSizesize);staticCCTableView*create(CCTableViewDataSource*dataSource,CCSizesize,CCNode*container);/***常用函数*setDirection,setVerticalFillOrder,*dequeueCell,cellAtIndex,*reloadData*///设置列表项cell的排列方向//CCScrollViewDirection://kCCScrollViewDirectionHorizontal横向排列//kCCScrollViewDirectionVertical纵向排列,默认方式virtualvoidsetDirection(CCScrollViewDirectioneDirection);CCScrollViewDirectiongetDirection();//设置列表项cell的排列顺序//当列表视图纵向排列Vertical时有效,从上到下显示的cell的排列顺序//kCCTableViewFillTopDown从小到大排列,即idx从小到大。0123//kCCTableViewFillBottomUp从大到小排列,即idx从大到小。3210voidsetVerticalFillOrder(CCTableViewVerticalFillOrderorder);CCTableViewVerticalFillOrdergetVerticalFillOrder();//从重排队列中获得一个可用的cell//因为在我们滑动cell的时候有些cell是显示的,有些不是显示出来的,把没有渲染的cell拿过来//这样就不用重新new出一个cell了,这样的话可以减小内存的开销CCTableViewCell*dequeueCell();//获得编号为idx的cellCCTableViewCell*cellAtIndex(unsignedintidx);//重新加载数据,当数据发生修改时调用voidreloadData();};//


5、关于排列方式

新创建的CCTableView默认的排列方式为:

(1)纵向排列: kCCScrollViewDirectionVertical

(2)按idx从大到小排列:kCCTableViewFillBottomUp

可以通过setDirection()设置排列方向,通过setVerticalFillOrder()设置排列顺序。

注意:若设置为横向排列,那么setVerticalFillOrder()就会失效了。


6、关于数据加载显示

当数据发生改变时,需要通过reloadData()重新加载数据。

否则显示的数据依旧还是未修改时的数据。


7、使用方法

(1)CCLayer继承两个相关类CCTableViewDataSource、CCTableViewDelegate。

(2)创建CCTableView,并设置可视区域大小。

(3)设置排列方向、排列顺序。

(4)设置委托代理setDelegate(this)。并实现两个继承类的相关函数。




【代码实战】

代码参考于cocos2dx的官方项目TestCpp。


1、资源图片

2、引入头文件和命名空间

//#include"cocos-ext.h"usingnamespacecocos2d::extension;//


3、继承CCTableViewDataSource、CCTableViewDelegate

并重写虚构函数及回调函数。

//classHelloWorld:publiccocos2d::CCLayer,publicCCTableViewDataSource,publicCCTableViewDelegate{public:virtualboolinit();staticcocos2d::CCScene*scene();CREATE_FUNC(HelloWorld);//继承于CCTableViewDataSourcevirtualCCSizetableCellSizeForIndex(CCTableView*table,unsignedintidx);//根据idx来设置每项cell的尺寸大小virtualCCTableViewCell*tableCellAtIndex(CCTableView*table,unsignedintidx);//获取编号为idx的cellvirtualunsignedintnumberOfCellsInTableView(CCTableView*table);//一共多少项cell//继承于CCTableViewDelegatevirtualvoidtableCellTouched(CCTableView*table,CCTableViewCell*cell);//某项cell被点击时回调函数virtualvoidscrollViewDidScroll(cocos2d::extension::CCScrollView*view);//滚动时回调函数virtualvoidscrollViewDidZoom(cocos2d::extension::CCScrollView*view);//放缩时回调函数};//


4、设置每个cell的大小

////根据idx来设置每项cell的尺寸大小CCSizeHelloWorld::tableCellSizeForIndex(CCTableView*table,unsignedintidx){if(idx==2)returnCCSizeMake(100,100);returnCCSizeMake(60,60);}//


5、设置cell总项数

////一共多少项cellunsignedintHelloWorld::numberOfCellsInTableView(CCTableView*table){return10;}//


6、设置每个cell的内容

在cell上添加一个精灵图片、一个Label标签。根据cell的编号idx,设置如上三类精灵图片。

//CCTableViewCell*HelloWorld::tableCellAtIndex(CCTableView*table,unsignedintidx){charIcon[20];//根据idx选中显示的图片charnumber[10];//显示label标签的数字sprintf(Icon,"sp%d.png",idx%3+1);sprintf(number,"%02d",idx);//也可以用cell=table->cellAtIndex(idx);CCTableViewCell*cell=table->dequeueCell();if(!cell){cell=newCCTableViewCell();cell->autorelease();//自动释放资源//添加一个精灵图片CCSprite*sprite=CCSprite::create(Icon);sprite->setAnchorPoint(CCPointZero);sprite->setPosition(ccp(0,0));cell->addChild(sprite,0,1);//添加一个label标签CCLabelTTF*label=CCLabelTTF::create(number,"Arial",20);label->setPosition(CCPointZero);label->setAnchorPoint(CCPointZero);cell->addChild(label,0,2);}else{//更换精灵图片,使用纹理CCTexture2D*texture=CCTextureCache::sharedTextureCache()->addImage(Icon);CCSprite*sprite=(CCSprite*)cell->getChildByTag(1);sprite->setTexture(texture);//更改图片编号CCLabelTTF*label=(CCLabelTTF*)cell->getChildByTag(2);label->setString(number);}returncell;}//


7、触摸到某个cell的回调函数

////某项cell被点击时回调函数voidHelloWorld::tableCellTouched(CCTableView*table,CCTableViewCell*cell){CCLOG("celltouchedatindex:%i",cell->getIdx());//控制台输出}//


8、创建两个CCTableView

一个横向、一个纵向。并设置相关属性、及委托代理。

//CCSizemysize=CCDirector::sharedDirector()->getVisibleSize();//横向CCTableViewCCTableView*tableView1=CCTableView::create(this,CCSizeMake(250,60));tableView1->setPosition(ccp(20,mysize.height/2-30));this->addChild(tableView1);//属性设置tableView1->setBounceable(false);//关闭弹性效果tableView1->setDirection(kCCScrollViewDirectionHorizontal);//横向tableView1->setDelegate(this);//委托代理tableView1->reloadData();//加载数据//纵向CCTableViewCCTableView*tableView2=CCTableView::create(this,CCSizeMake(60,250));tableView2->setPosition(ccp(mysize.width-150,mysize.height/2-120));this->addChild(tableView2);//属性设置tableView2->setDirection(kCCScrollViewDirectionVertical);//纵向tableView2->setVerticalFillOrder(kCCTableViewFillTopDown);//从小到大排列tableView2->setDelegate(this);//委托代理tableView2->reloadData();//加载数据//


9、运行结果

10、分析与总结

(1)注意CCTableView继承于CCScrollView,即也是继承于CCLayer,故它会忽略锚点的设置,其锚点始终为(0,0)。

(2)大家发现没有,左边那组关闭弹性效果后,触摸移动起来感觉很不爽呀。

(3)编号为02的旁边为何会有这么大的间隔呢?这是因为我在设置单元项cell大小的时候,故意设置了编号为02的大小为100*100,其他的均为60*60。

(4)还有一点,倘若你要修改某一项的数据时,修改完后,记得要重新加载数据reloadData()。