Cocos2d-x 学习笔记(22) TableView
【Cocos2d-x 学习笔记 】目录
1. 简介
TableView直接继承了ScrollView和ScrollViewDelegate。说明TableView能实现ScrollView拖动container的效果。重写了ScrollViewDelegate的委托方法scrollViewDidScroll,对ScrollView功能进行“拓展”。
TableView和ScrollView都能够在可视范围内拖动container,在可视范围内展示部分的container,但是两者也有明显的不同。
ScrollView是一次性将要展示的所有元素加到container,可视范围只是在其中选取一部分显示。
TableView是对container内的cell“动态加载”,当cell需要出现在可视范围的时候再把cell加到container,cell离开可视范围则把cell缓存。TableView的“动态加载”需要ScrollView委托的scrollViewDidScroll方法实时监测可视范围内cell的变化情况。
ScrollView可以不限方向拖动和缩放。TableView只能拖动,且拖动方向限制为纵向或横向。
2. TableViewCell
TableView的container是“动态加载”“动态删除”。所谓“动态”依赖着container的基本单位cell,“加载”“删除”指的是对cell的操作。
TableViewCell直接继承Node。
cell有成员变量idx,是cell的下标或者序号,用来识别cell。idx为-1时表明该cell处于无效状态,此时cell并没有在可视范围呈现,而是进行缓存。
我们通过对cell增加Sprite Label等子节点,让cell有了图像和文本等效果。
cell按序排列就成为了container。
3. TableViewDataSource TableViewDelegate
有TableView对象的Layer等都要直接继承TableViewDataSource和TableViewDelegate,根据需要可以重写这些方法。
TableViewDataSource是供我们自定义TableView相关数据处理方法的类,该类中的方法需要我们重写。
virtual Size tableCellSizeForIndex(TableView* table, ssize_t idx); //根据idx返回cell的size
virtual Size cellSizeForTable(TableView* table); //返回cell的size
virtual TableViewCell* tableCellAtIndex(TableView *table, ssize_t idx) = ; //根据idx返回cell
virtual ssize_t numberOfCellsInTableView(TableView *table) = ; //返回cell总数
TableViewDelegate委托类直接继承ScrollViewDelegate。
virtual void tableCellTouched(TableView* table, TableViewCell* cell) = ;
virtual void tableCellHighlight(TableView* table, TableViewCell* cell);
virtual void tableCellUnhighlight(TableView* table, TableViewCell* cell);
virtual void tableCellWillRecycle(TableView* table, TableViewCell* cell);
4. 部分属性
- TableViewCell *_touchedCell
在Touch事件3个回调函数中使用到,指的是当前触摸到的cell。我们可以对当前触摸的cell进行处理。
- VerticalFillOrder _vordering
纵向排列顺序的枚举VerticalFillOrder包含从小到大TOP_DOWN,从大到小BOTTOM_UP。
- std::set<ssize_t>* _indices
可视idx容器,存储可视范围内cell的idx。
- std::vector<float> _vCellsPositions
通过_updateCellPositions方法,根据我们对cell数量的设置和size的设置,计算每个cell起始点x或y并储存到该容器。容器最后多余一个位置,存储container的长度。
- Vector<TableViewCell*> _cellsUsed
可视容器。存储可视区域内cell的容器。
- Vector<TableViewCell*> _cellsFreed
缓存容器。存储离开可视区域内cell的容器,按队列形式存储。这些cell的idx被置-1,表明无效cell。
- TableViewDataSource* _dataSource
- TableViewDelegate* _tableViewDelegate
两个委托类。
- Direction _oldDirection
和_direction搭配使用,在构造函数和reloadData方法开始时设为NONE,用于设置container的初始位置
- bool _isUsedCellsDirty
脏标记,用于给可视容器按idx重新排序。可视容器cell数量发生变化时会置true。
5. 主要方法
- create(TableViewDataSource* dataSource, Size size, Node *container)
设置了默认排列方式BOTTOM_UP,方向VERTICAL。
调用了_updateCellPositions方法:设置容器_vCellsPositions。
调用了_updateContentSize方法:设置container大小,长度为所有cell之和;设置container的位置。
执行的setDelegate方法,将this设为了_delegate。
- reloadData()
重新加载TableView,相当于刷新一次TableView。包括清空可视容器和可视idx容器,cell存入缓存容器,更新_vCellsPositions,重新设置container大小和位置,执行scrollViewDidScroll更新可视范围cell的状态。
在执行setVerticalFillOrder方法设置新的纵向排列顺序之后,会执行该方法。
- cellAtIndex(ssize_t idx)
根据idx返回cell。idx和cell必须在可视idx容器和可视容器中,即cell必须在可视范围内,无效cell不会被返回。
- scrollViewDidScroll(ScrollView* view)
该方法用于更新可视范围内cell的状态。
该方法在设置container位置的setContentOffset和reloadData会被调用
create执行的setDelegate方法,将this设为了_delegate,从而实现了setContentOffset方法执行时会调用该方法更新cell。
主要逻辑是:
1. 判断脏标记_isUsedCellsDirty。为true时要对可视容器_cellsUsed内的cell按idx从小到大排序。TableView的cell是有序排列的。
2. 计算offset。该坐标offset把container的坐标乘-1,即“container相对可视范围的位置”转换成“可视范围相对container的位置”。
转换的原因是,我们之后需要计算可视范围cell的idx,而cell是按顺序排列在container中。通过可视范围相对container的位置,就能很容易理解并且计算当前可视范围内cell的idx了。
3. 计算可视范围内cell最小的idx(startIdx)和最大的idx(endIdx)。该范围内的cell正出现在可视区域内。
4. 越界处理,即“删除”从可视范围内离开的cell。
可视容器_cellsUsed不为空时,容器内的cell已经按idx从小到大排序,所以判断是分别从容器第一个和最后一个cell开始,判断idx与startIdx或endIdx的关系。如果需要“删除”,则执行_moveCellOutOfSight方法进行“删除”,并继续判断下一个idx,直到所有可视容器内的cell idx都在范围之中。
5. 新cell的处理。
没有新cell时,可视范围内的idx和存储可视cell idx的容器_indices显然是一一对应。当出现新cell,其idx一定不在可视idx容器_indices之中,需要执行updateCellAtIndex方法,添加该cell的信息到容器中。
- _moveCellOutOfSight(TableViewCell *cell)
该方法是对离开可视区域内的cell进行删除和缓存。
scrollViewDidScroll需要检测当前cell
主要逻辑是:
1. 调用delegate的tableCellWillRecycle方法。该委托方法
2. 对参数cell进行以下操作:
加入到缓存容器_cellsFreed;
从可视容器_cellsUsed删除;
其idx从可视下标容器_indices删除;
其idx置-1;
container删除该子节点cell。
- _indexFromOffset(Vec2 offset)
根据坐标求出cell的下标。根据坐标在容器_vCellsPositions中进行二分查找,确定坐标对应的下标。
- _offsetFromIndex(ssize_t index)
根据cell序号返回坐标。通过序号和_vCellsPositions序号一一对应的关系,返回坐标值。
在_setIndexForCell方法中,根据index给cell设置位置时,需要通过该方法计算位置。
- updateCellAtIndex(ssize_t idx)
该方法用于对新出现在可视范围内的cell,更新容器的相关信息。
该方法只在scrollViewDidScroll方法监测到新cell出现时才会被调用。
主要逻辑是:
1. 生成参数idx对应的cell。
调用了dataSource的tableCellAtIndex方法,该方法需要被重写。
在Cocos2dx官方Demo中,tableCellAtIndex主要逻辑是:执行dequeueCell方法。尝试从缓存容器_cellsFreed中弹出第一个cell。如果缓存容器中没有cell,则新建cell。如果弹出了cell,该cell作为生成的cell。当然,无论是不是新cell,cell显示的下标idx都需要改为参数idx。
2. 设置cell的idx和位置。执行的是_setIndexForCell方法。
3. 把cell加入到TableView中:cell作为container的子节点。cell加入可视容器_cellsUsed。idx加入可视idx容器_indices。置脏标记,用于对可视容器重新排序。
6. Touch事件的3个回调函数
- onTouchBegan
1. TableView存在不可见的父节点时,返回false。
2. 执行父类ScrollView的onTouchBegan方法,保存Touch信息,返回值作为TableView的该方法返回值。
3. 是单点触摸时,通过触摸点坐标计算出当前触摸了哪个cell。如果cell存在,执行delegate的tableCellHighlight方法,可以对cell执行高亮等操作。
4. 是两点触摸且存在正在触摸的cell(_touchedCell)时,执行delegate的tableCellUnhighlight方法,可以取消该cell的高亮。然后_touchedCell置空。
- onTouchMoved
1. 执行父类ScrollView的onTouchMoved方法,对container进行拖动。
2. 如果拖动时存在_touchedCell,执行delegate的tableCellUnhighlight方法,可以取消该cell的高亮。然后_touchedCell置空。
- onTouchEnded
1. 如果存在_touchedCell,且触摸结束点在可视范围内,执行delegate的tableCellUnhighlight和tableCellTouched方法。
正常情况下,_touchedCell在onTouchMoved方法应该置空,仍存在时,说明onTouchMoved时移动距离过小。
2. 执行父类ScrollView的onTouchEnded方法。
本文地址:https://www.cnblogs.com/deepcho/p/cocos2dx-tableview.html
Cocos2d-x 学习笔记(22) TableView的更多相关文章
- Ext.Net学习笔记22:Ext.Net Tree 用法详解
Ext.Net学习笔记22:Ext.Net Tree 用法详解 上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat=&q ...
- SQL反模式学习笔记22 伪键洁癖,整理数据
目标:整理数据,使不连续的主键Id数据记录变的连续. 反模式:填充断档的数据空缺. 1.不按照顺序分配编号 在插入新行时,通过遍历表,找到的第一个未分配的主键编号分配给新行,来代替原来自动分配的伪主键 ...
- Hadoop学习笔记—22.Hadoop2.x环境搭建与配置
自从2015年花了2个多月时间把Hadoop1.x的学习教程学习了一遍,对Hadoop这个神奇的小象有了一个初步的了解,还对每次学习的内容进行了总结,也形成了我的一个博文系列<Hadoop学习笔 ...
- [原创]java WEB学习笔记22:MVC案例完整实践(part 3)---多个请求对应一个Servlet解析
本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...
- ArcGIS API for JavaScript 4.2学习笔记[22] 使用【QueryTask类】进行空间查询 / 弹窗样式
上一篇写道,使用Query类进行查询featureLayer图层的要素,也简单介绍了QueryTask类的使用. 这一篇博文继续推进,使用Query类和QueryTask类进行空间查询,查询USA的著 ...
- Linux下汇编语言学习笔记22 ---
这是17年暑假学习Linux汇编语言的笔记记录,参考书目为清华大学出版社 Jeff Duntemann著 梁晓辉译<汇编语言基于Linux环境>的书,喜欢看原版书的同学可以看<Ass ...
- C++学习笔记22:设备
设备类型 设备文件的性质 设备文件不是普通的磁盘文件 读写设备的数据需要与相应的设备驱动器通信 设备文件的类型 字符设备:读写串行数据字节流,如串口.终端等 块设备:随机读写固定尺寸数据块,如磁盘设备 ...
- JavaScript高级程序设计(第三版)学习笔记22、24、25章
第22章,高级技巧 高级函数 安全的类型检测 typeof会出现无法预知的行为 instanceof在多个全局作用域中并不能正确工作 调用Object原生的toString方法,会返回[Object ...
- C++学习笔记22,普通函数重载(1)
转载请注明出处:http://blog.csdn.net/qq844352155/article/details/31353325 该博文仅用于交流学习,请慎用于不论什么商业用途,本博主保留对该博文的 ...
随机推荐
- maven的使用解说
maven周期及项目中的应用: 周期如下: 1.default生命周期,部署项目(jar包的依赖管理) 2.clear生命周期,项目清理工作 3.site生命周期,处理项目中产生的文档信息 应用: 1 ...
- Java第三次作业第二题
2. [请复制本程序,作为java程序代码,进行编译,补充填写缺失代码部分,并实现题目要求功能,从而获得空白填写所需的内容.] 定义3个线程,模拟红绿灯的效果 一个线程控制画一个实心红圆 一个线程控制 ...
- Nginx限流
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 在当今流量徒增的互联网时代,很多业务场景都会涉及到高并发.这个时候接口进行限流是非常有必要的,而限流是Ngin ...
- Linux 修改 ls 时间显示格式
[root@CentosTe tmp]# export TIME_STYLE='+%Y-%m-%d %H:%M:%S'[root@CentosTe tmp]# ll总计 24-rwx------ 1 ...
- 使用python发邮件(qq邮箱)
今天打算用QQ邮箱作为示例使用的邮箱,其他邮箱基本操作一样. 第一步:首先获取QQ邮箱授权码 1.进入QQ邮箱首页,点击设置,如图, 2.然后点击账户 3.拉到这个地方,开启POP3/SMTP服务服务 ...
- 第六届蓝桥杯java b组第五题
九数组分数 1,2,3…9 这九个数字组成一个分数,其值恰好为1/3,如何组法? 下面的程序实现了该功能,请填写划线部分缺失的代码. public class A { public static vo ...
- CentOS8-网卡配置
一. 介绍 Centos8系统更新,新的版本让人看起来感觉很舒服,这时有人会配置CentOS8系统的网卡使系统上网,就会遇到配置好的网卡不会生效,自己想想和配置CentOS7的时候一个样啊,CentO ...
- 11 种在大多数教程中找不到的JavaScript技巧
当我开始学习JavaScript时,我把我在别人的代码.code challenge网站以及我使用的教程之外的任何地方发现的每一个节省时间的技巧都列了一个清单. 在这篇文章中,我将分享11条我认为特别 ...
- Angular 开发NPM第三方包
步骤: 创建第三方包 > 开发第三方包 > 测试第三方包 > 发布第三方包 > 使用第三方包 实例: 第一步:创建第三方包;; (创建项目,项目下创建第三方库) 1. 新建项目 ...
- 2019-ccpc秦皇岛现场赛
https://www.cnblogs.com/31415926535x/p/11625462.html 昨天和队友模拟了下今年秦皇岛的区域赛,,,(我全程在演 题目链接 D - Decimal 签到 ...