cocos2dx基础篇(13)——列表视图CCTableView

【唠叨】

    关于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从小到大。0 1 2 3
			BOTTOM_UP      //从大到小排列,即idx从大到小。3 2 1 0。默认方式
//

    (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上面。

    常用操作如下:

//
	class CCTableViewCell: public CCNode, public CCSortableObject
	{
		//设置cell的唯一标示符idx
		void setIdx(unsigned int uIdx);
		unsigned int getIdx();
	};
//

 

2、CCTableViewDataSource

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

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

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

    其中:

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

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

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

//
	class CCTableViewDataSource
	{
		//设置每项cell的尺寸大小
		virtual CCSize cellSizeForTable(CCTableView *table);

		//根据idx来设置每项cell的尺寸大小
		virtual CCSize tableCellSizeForIndex(CCTableView *table, unsigned int idx);

		//获取编号为idx的cell
		//若还未生成idx的cell,那么就创建该项cell的内容
		virtual CCTableViewCell* tableCellAtIndex(CCTableView* table, unsigned int idx) = 0;

		//列表中一共多少项cell
		virtual unsigned int numberOfCellsInTableView(CCTableView *table) = 0;
	};
//

 

3、CCTableViewDelegate

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

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

//
	class CCTableViewDelegate : public CCScrollViewDelegate
	{
		//当cell被点击时的回调函数,用于处理被触摸的cell数据
		virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell) = 0;

		//继承于CCScrollView
		virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view) {}  //滚动时回调函数
		virtual void scrollViewDidZoom(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并为它开辟内存空间。

//
class CCTableView : public CCScrollView, public CCScrollViewDelegate
{
/**
 *		2种创建
 */
	//dataSource:一般为this
	//size:列表视图的可视区域的尺寸大小
	//container:自定义CCLayer容器。一般不推荐使用自定义容器
	static CCTableView* create(CCTableViewDataSource* dataSource, CCSize size);
	static CCTableView* create(CCTableViewDataSource* dataSource, CCSize size, CCNode* container);


/**
 *		常用函数
 *		setDirection , setVerticalFillOrder ,
 *		dequeueCell , cellAtIndex ,
 *		reloadData
 */
	//设置列表项cell的排列方向
	//CCScrollViewDirection:
	//      kCCScrollViewDirectionHorizontal        横向排列
	//      kCCScrollViewDirectionVertical          纵向排列,默认方式
	virtual void setDirection(CCScrollViewDirection eDirection);
	CCScrollViewDirection getDirection();

	//设置列表项cell的排列顺序
	//当列表视图纵向排列Vertical时有效,从上到下显示的cell的排列顺序
	//		kCCTableViewFillTopDown					从小到大排列,即idx从小到大。0 1 2 3
	//		kCCTableViewFillBottomUp				从大到小排列,即idx从大到小。3 2 1 0
	void setVerticalFillOrder(CCTableViewVerticalFillOrder order);
	CCTableViewVerticalFillOrder getVerticalFillOrder();

	//从重排队列中获得一个可用的cell
	//因为在我们滑动cell的时候有些cell是显示的,有些不是显示出来的,把没有渲染的cell拿过来
	//这样就不用重新new出一个cell了,这样的话可以减小内存的开销
	CCTableViewCell* dequeueCell();

	//获得编号为idx的cell
	CCTableViewCell* cellAtIndex(unsigned int idx);

	//重新加载数据,当数据发生修改时调用
	void reloadData();
};
//

 

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、资源图片

wKiom1P8berQQWTMAAATIvbAoeQ250.jpg    wKioL1P8bwKArpseAAAU7Ih-51U944.jpg    wKiom1P8bevz6AOGAAANgkMX34Q446.jpg

    

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

//
	#include "cocos-ext.h"
	using namespace cocos2d::extension;
//

 

3、继承CCTableViewDataSource、CCTableViewDelegate

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

//
	class HelloWorld : public cocos2d::CCLayer,public CCTableViewDataSource, public CCTableViewDelegate
	{
	public:
		virtual bool init();  
		static cocos2d::CCScene* scene();
		CREATE_FUNC(HelloWorld);


		//继承于CCTableViewDataSource
		virtual CCSize tableCellSizeForIndex(CCTableView* table, unsigned int idx);       //根据idx来设置每项cell的尺寸大小
		virtual CCTableViewCell* tableCellAtIndex(CCTableView* table, unsigned int idx);  //获取编号为idx的cell
		virtual unsigned int numberOfCellsInTableView(CCTableView* table);                //一共多少项cell

		//继承于CCTableViewDelegate
		virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell);         //某项cell被点击时回调函数
		virtual void scrollViewDidScroll(cocos2d::extension::CCScrollView* view);         //滚动时回调函数
		virtual void scrollViewDidZoom(cocos2d::extension::CCScrollView* view);           //放缩时回调函数
	};
//

 

4、设置每个cell的大小

//
	//根据idx来设置每项cell的尺寸大小
	CCSize HelloWorld::tableCellSizeForIndex(CCTableView* table, unsigned int idx)
	{
		if(idx == 2) return CCSizeMake(100,100);
		return CCSizeMake(60,60);
	}
//

 

5、设置cell总项数

//
	//一共多少项cell
	unsigned int HelloWorld::numberOfCellsInTableView(CCTableView* table)
	{
		return 10;
	}
//

 

6、设置每个cell的内容

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

//
	CCTableViewCell* HelloWorld::tableCellAtIndex(CCTableView* table, unsigned int idx)
	{
		char Icon[20];   //根据idx选中显示的图片
		char number[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 = new CCTableViewCell();
			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);
		}

		return cell;
	}
//

 

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

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

 

8、创建两个CCTableView

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

//
		CCSize mysize = CCDirector::sharedDirector()->getVisibleSize();


	//横向CCTableView
		CCTableView* 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();                                       //加载数据


	//纵向CCTableView
		CCTableView* 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、运行结果

wKiom1P8eo_RjdDIAANxlcu3Q5g534.gif

    

10、分析与总结

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

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

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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值