cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
来源:互联网 发布:淘宝白号怎么升一心 编辑:程序博客网 时间:2024/06/06 00:33
cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
分类: cocos2d-x 源码分析2014-06-17 10:51 57人阅读 评论(0) 收藏 举报
cocos2d-x游戏源码
目录(?)[+]
cocos2d-x源码总目录
http://blog.csdn.net/u011225840/article/details/31743129
源码来自2.x,转载请注明
1.继承结构
首先来看下CCTableView的继承结构
从继承结构上看,CCTableView是一种CCScrollView,所以为了研究CCTableView的源码,清先去了解CCScrollView的源码http://blog.csdn.net/u011225840/article/details/30033501。
其次,CCTableView也继承了CCScrollViewDelegate,从后面的源码分析中,我们可以看出主要是为了实现scrollViewDidScroll这个函数。从而使用CCScrollView的滚动时,可以实现CCTableView自己本身的操作。(如果你看到这里不懂,请务必先弄懂CCScrollView的源码。)
最后,除了继承结构,我们还需要了解三个重要的类。
CCTableViewCell,CCTableViewDelegate,CCTableViewDataSource。通过这三个类,CCTableView将数据与其他操作解耦。
2.相关类的分析
2.1CCTableViewCell
CCtableViewCell主要是含有一个唯一的标识符,允许TableView通过不同的idx来更新TableviewCell。
一般情况下,会写一个CustomCell来继承该类,该Cell上有每一个cell的样式(含有label?含有sprite?全在该cell中实现)
- class CCTableViewCell: public CCNode, public CCSortableObject
- {
- public:
- CCTableViewCell() {}
- /**
- * The index used internally by SWTableView and its subclasses
- */
- unsigned int getIdx();
- void setIdx(unsigned int uIdx);
- /**
- * Cleans up any resources linked to this cell and resets <code>idx</code> property.
- */
- void reset();
- void setObjectID(unsigned int uIdx);
- unsigned int getObjectID();
- private:
- unsigned int m_uIdx;
- };
2.2CCTableViewDataSource
CCTableViewDataSource是非常重要的一个类,TableView的数据相关的处理都与该类有关,请看他提供的四个函数,注释已经给出哦。
一般情况下,我们会让一个Custom类来继承他并实现方法。该Custom类一般是继承DataSource,TableViewDelegate,与一个CClayer,并含有一个CCTableView。
(在文章的最后,我会给出一个例子)。
- //根据不同的idx,来告诉tableview cell的大小
- virtual CCSize tableCellSizeForIndex(CCTableView *table, unsigned int idx) {
- return cellSizeForTable(table);
- };
- //提供一个通用的方法,给出table的cell大小,如果该table的cell大小都一样,一般都一样。。
- virtual CCSize cellSizeForTable(CCTableView *table) {
- return CCSizeZero;
- };
- //根据不同的idx,获得table的相应cell,一会分析table的dequeceCell时,再详细讲解此方法。
- virtual CCTableViewCell* tableCellAtIndex(CCTableView *table, unsigned int idx) = 0;
- //返回table的cell个数。
- virtual unsigned int numberOfCellsInTableView(CCTableView *table) = 0;
2.3 CCTableViewDelegate
提供了几个Delegate函数,以供TableView使用。Delegate的用法我在CCScrollView源码分析中已经说过,这里不再赘述。
virtual void tableCellTouched(CCTableView* table, CCTableViewCell* cell) = 0;
这里只说下必须实现的这个函数,当table通过idx获取用户正在触摸该cell后,一定会调用该方法。(选择某个物件后,给人物穿上,就是通过这个方法来响应。)
3.CCTableView源码分析
3.1创建时
CCTableView提供了两个create函数
create(CCTableViewDataSource* dataSource, CCSize size);
create(CCTableViewDataSource* dataSource, CCSize size, CCNode *container);
第一个函数,调用了第二个,将container置为NULL。
下面来看第二个函数。
- CCTableView* CCTableView::create(CCTableViewDataSource* dataSource, CCSize size, CCNode *container)
- {
- CCTableView *table = new CCTableView();
- table->initWithViewSize(size, container);
- table->autorelease();
- table->setDataSource(dataSource);
- table->_updateCellPositions();
- table->_updateContentSize();
- return table;
- }
话说这种风格也不怕堆内存空间不足么。
发现三个重要的函数:
3.1.1 initWithViewSize
- bool CCTableView::initWithViewSize(CCSize size, CCNode* container/* = NULL*/)
- {
- if (CCScrollView::initWithViewSize(size,container))
- {
- m_pCellsUsed = new CCArrayForObjectSorting();
- m_pCellsFreed = new CCArrayForObjectSorting();
- m_pIndices = new std::set<unsigned int>();
- m_eVordering = kCCTableViewFillBottomUp;
- this->setDirection(kCCScrollViewDirectionVertical);
- CCScrollView::setDelegate(this);
- return true;
- }
- return false;
- }
cellsUsed是用来存放正在使用的,显示在view上面的cell。
cellsFreed是用来存放暂时不使用的,没在view上面显示的cell(从cellsUsed被移除后添加进cellsFreed),cellsFreed提供了一种缓存机制。允许我们从tableCellAtIndex中拿到cells,不需要重新创建他,只需要根据idx更新下显示。
indices是用来存放每个cell应该占据的位置区域值。
3.1.2 _updateCellPositions
根据CCTableView呈现的方向以及order,给indices赋值。
- void CCTableView::_updateCellPositions() {
- //根据dataSource,更新cell的位置。
- int cellsCount = m_pDataSource->numberOfCellsInTableView(this);
- m_vCellsPositions.resize(cellsCount + 1, 0.0);
- if (cellsCount > 0)
- {
- float currentPos = 0;
- CCSize cellSize;
- for (int i=0; i < cellsCount; i++)
- {
- m_vCellsPositions[i] = currentPos;
- CCLog("The postion is %f",currentPos);
- //根据idx获取到相应cell的size
- cellSize = m_pDataSource->tableCellSizeForIndex(this, i);
- switch (this->getDirection())
- {
- case kCCScrollViewDirectionHorizontal:
- currentPos += cellSize.width;
- break;
- default:
- currentPos += cellSize.height;
- break;
- }
- }
- //n个cell需要n+1个Pos 来指定位置
- m_vCellsPositions[cellsCount] = currentPos;//1 extra value allows us to get right/bottom of the last cell
- CCLog("The postion is %f",currentPos);
- }
- }
3.1.3 _updateContentSize
这个方法调整了CCTableView的大小与偏移。(注意,调整偏移的时候,会调用scrollViewDidScroll方法。)
- void CCTableView::_updateContentSize()
- {
- CCSize size = CCSizeZero;
- unsigned int cellsCount = m_pDataSource->numberOfCellsInTableView(this);
- //获取到最大的长与宽
- if (cellsCount > 0)
- {
- float maxPosition = m_vCellsPositions[cellsCount];
- switch (this->getDirection())
- {
- case kCCScrollViewDirectionHorizontal:
- size = CCSizeMake(maxPosition, m_tViewSize.height);
- break;
- default:
- size = CCSizeMake(m_tViewSize.width, maxPosition);
- break;
- }
- }
- //获取后调用CCScrollView的setContenSize
- this->setContentSize(size);
- //调整方向与初始偏移offset
- if (m_eOldDirection != m_eDirection)
- {
- if (m_eDirection == kCCScrollViewDirectionHorizontal)
- {
- this->setContentOffset(ccp(0,0));
- }
- else
- {
- //这里其实不是很懂
- this->setContentOffset(ccp(0,this->minContainerOffset().y));
- }
- m_eOldDirection = m_eDirection;
- }
- }
如注释所示,我有个小问题,如果是垂直方向的,则会把初始位置放到minContainerOffset上,为何这样,没懂。。。
下面一节重点讲解scrollviewDidScroll
3.2 滚动时
根据父类CCScrollView,每次设置偏移后,会调用scrollviewDidScroll方法。
- void CCTableView::scrollViewDidScroll(CCScrollView* view)
- {
- //继承自CCScrollViewDelegate,并且根据CCScrollView的源码,每次移动时(setContentOffset函数),都会调用这个函数
- //没有任何元素
- unsigned int uCountOfItems = m_pDataSource->numberOfCellsInTableView(this);
- if (0 == uCountOfItems)
- {
- return;
- }
- //tableviewdelegate的DidScroll调用
- if(m_pTableViewDelegate != NULL) {
- m_pTableViewDelegate->scrollViewDidScroll(this);
- }
- unsigned int startIdx = 0, endIdx = 0, idx = 0, maxIdx = 0;
- //需要乘以-1的原因很简单,当offset处于正数时,即为cell在初始位置还要往右拉,此时得到的startIdx肯定是不存在的。
- CCPoint offset = ccpMult(this->getContentOffset(), -1);
- maxIdx = MAX(uCountOfItems-1, 0);
- if (m_eVordering == kCCTableViewFillTopDown)
- {
- offset.y = offset.y + m_tViewSize.height/this->getContainer()->getScaleY();
- }
- //查到起始的startIdx
- startIdx = this->_indexFromOffset(offset);
- //CCLog("The offset is %f",offset.x);
- //CCLog("The start index is %d",startIdx);
- if (startIdx == CC_INVALID_INDEX)
- {
- startIdx = uCountOfItems - 1;
- }
- if (m_eVordering == kCCTableViewFillTopDown)
- {
- offset.y -= m_tViewSize.height/this->getContainer()->getScaleY();
- }
- else
- {
- offset.y += m_tViewSize.height/this->getContainer()->getScaleY();
- }
- //起始offset加上显示View的宽度就是endIdx的offset
- offset.x += m_tViewSize.width/this->getContainer()->getScaleX();
- endIdx = this->_indexFromOffset(offset);
- //如果endIdx 超过,则将endIdx置为最大值
- if (endIdx == CC_INVALID_INDEX)
- {
- endIdx = uCountOfItems - 1;
- }
- if(startIdx > endIdx)
- {
- int tmp = startIdx;
- startIdx = endIdx;
- endIdx = tmp;
- }
- if (m_pCellsUsed->count() > 0)
- {
- CCTableViewCell* cell = (CCTableViewCell*)m_pCellsUsed->objectAtIndex(0);
- //找出正在使用的cell,只要是idx小于startIdx的,就移出。
- idx = cell->getIdx();
- while(idx <startIdx)
- {
- this->_moveCellOutOfSight(cell);
- if (m_pCellsUsed->count() > 0)
- {
- cell = (CCTableViewCell*)m_pCellsUsed->objectAtIndex(0);
- idx = cell->getIdx();
- }
- else
- {
- break;
- }
- }
- }
- if (m_pCellsUsed->count() > 0)
- {
- CCTableViewCell *cell = (CCTableViewCell*)m_pCellsUsed->lastObject();
- idx = cell->getIdx();
- //同上,移除所有大于endIdx的cell
- while(idx <= maxIdx && idx > endIdx)
- {
- this->_moveCellOutOfSight(cell);
- if (m_pCellsUsed->count() > 0)
- {
- cell = (CCTableViewCell*)m_pCellsUsed->lastObject();
- idx = cell->getIdx();
- }
- else
- {
- break;
- }
- }
- }
- //更新在start和end之间的cell
- for (unsigned int i=startIdx; i <= endIdx; i++)
- {
- //if ([m_pIndices containsIndex:i]),indices存在即表明该位置上的cell已经被update。
- if (m_pIndices->find(i) != m_pIndices->end())
- {
- continue;
- }
- this->updateCellAtIndex(i);
- }
- }
0 0
- cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
- cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
- cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
- Cocos2d—X游戏开发之CCTableView详解(十一)(附源码)
- CCTableView源码分析
- cocos2d-x 源码分析
- cocos2d-x 源码分析
- Cocos2d-x 实例源码分析之 前沿
- COCOS2D-X源码分析之初始化游戏
- cocos2d-x源码分析之Director::drawScene()
- cocos2d-x 之 CCArray 源码分析
- Cocos2d-x HelloWorld 之源码分析
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(1)----cocos2D-X渲染结构
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(1)----cocos2D-X渲染结构
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(1)----cocos2D-X渲染结构
- cocos2D-X源码分析之从cocos2D-X学习OpenGL(1)----cocos2D-X渲染结构
- Cocos2d-x 源码分析 : Scheduler(定时器) 源码分析
- Cocos2d-x 源码分析 : Scheduler(定时器) 源码分析
- 物研究所做一位科研人员
- 绕开国网 特斯拉与小伙伴自组充电网
- WordCount运行详解
- U-Boot编译过程完全分析 (wh)
- miracast
- cocos2d-x 源码分析 之 CCTableView源码分析(附使用方法讨论)
- Sublime Text 3 快捷键汇总
- Android 用Intent 传递对象之 Parcel
- PLSQL开发笔记和小结
- Xcode6:解决_NSURLAuthenticationMethodServerTrust异常问题
- mysql 两表结果集取差集
- C++转型操作符:const_cast、dynamic_cast、static_cast、reinterpret_cast
- js -- 绑定
- 裘宗燕:C/C++ 语言中的表达式求值顺序