CocosCreator开发笔记(5)-ScrollView之动态更新的优化原理
2018-01-19 10:08
423 查看
ScrollView是比较常用的UI组件之一,游戏中的任务榜、排行榜都少不了它,实际使用中存在一个问题,例如:在排行榜中要显示前100名玩家,如果真的把这100名玩家的信息全部创建,并加载进ScrollView,对移动设备的宝贵内存会是巨大的浪费。其实玩家在屏幕上总能看到的最多只有7、8项而已,所以实际上只用创建比显示多一点的数量,再通过缓冲区实时动态更新数据,就可以给玩家呈现出尽可能多数量的列表(依内存而定,理论上无限),即节省内存,也不影响性能。
在CocosCreate官方提供的example中,有个ScrollView的例子,就使用了动态更新数据,我把它摘出来做为一个单独的工程,加上中文注释,并对代码稍做改动,运行截图如下所示:
可以看到,列表中显示一共有100行,但一屏最多展示7.5行,而实际上在内存中只真正创建了15项,所有看到的这100行,都是在上下滚动事件中,通过动态更新这15项的坐标和内容来实现的。要了解它的运行原理,先看下图:
如图把ScrollView分成三部分,按区域从小到大依次是:
1、屏幕可见区。指屏幕上玩家可看可操作的列表区域,在此demo中有7.5行;
2、缓冲区。指内存中真正创建了的列表所占的区域,在此demo中有15行;
3、content区。指整个ScrollView要显示的区域,在此demo中有100行;
下面再分三种情况讲解:
1、刚初始化完成时:此时在右侧按钮上提示有100行,实际上只创建了第1-15行,而玩家能看到的是第1-7行。如果玩家想要看到更多,必然会向上或向下滚动屏幕;
2、向上滚动时:在移动设备上,如果玩家想要看到下面的行,所做的操作是触摸往上滑动,则整个content区往上移动,也带动content区的item往上移动,update函数会不断遍历所创建的15项item,如果检测到某item的y坐标超出了缓冲区的上边界(该item已经被玩家看过或不想再看),则把该item往下移动一个缓冲区的高度(移动该item到玩家即将看到的位置),并更新它的显示ID;
3、向下滚动时:同理,content区的item往下移动,update不断遍历所创建的15项item,如果检测到某item的y坐标越过了缓冲区的下边界(该item已经被玩家看过或不想再看),则把该item往上移动一个缓冲区的高度(移动该item到玩家即将看到的位置),并更新它的显示ID;
关键代码如下所示:
在此demo中,ScrollView列表显示的item其实是个按钮,而它是做为预制资源,其实可以在Creator中编辑成各种UI,并不局限于按钮形式。
最后,附上该Creator工程完整源代码的github地址:https://github.com/foupwang/CocosCreatorScrollViewDemo.git
在CocosCreate官方提供的example中,有个ScrollView的例子,就使用了动态更新数据,我把它摘出来做为一个单独的工程,加上中文注释,并对代码稍做改动,运行截图如下所示:
可以看到,列表中显示一共有100行,但一屏最多展示7.5行,而实际上在内存中只真正创建了15项,所有看到的这100行,都是在上下滚动事件中,通过动态更新这15项的坐标和内容来实现的。要了解它的运行原理,先看下图:
如图把ScrollView分成三部分,按区域从小到大依次是:
1、屏幕可见区。指屏幕上玩家可看可操作的列表区域,在此demo中有7.5行;
2、缓冲区。指内存中真正创建了的列表所占的区域,在此demo中有15行;
3、content区。指整个ScrollView要显示的区域,在此demo中有100行;
下面再分三种情况讲解:
1、刚初始化完成时:此时在右侧按钮上提示有100行,实际上只创建了第1-15行,而玩家能看到的是第1-7行。如果玩家想要看到更多,必然会向上或向下滚动屏幕;
2、向上滚动时:在移动设备上,如果玩家想要看到下面的行,所做的操作是触摸往上滑动,则整个content区往上移动,也带动content区的item往上移动,update函数会不断遍历所创建的15项item,如果检测到某item的y坐标超出了缓冲区的上边界(该item已经被玩家看过或不想再看),则把该item往下移动一个缓冲区的高度(移动该item到玩家即将看到的位置),并更新它的显示ID;
3、向下滚动时:同理,content区的item往下移动,update不断遍历所创建的15项item,如果检测到某item的y坐标越过了缓冲区的下边界(该item已经被玩家看过或不想再看),则把该item往上移动一个缓冲区的高度(移动该item到玩家即将看到的位置),并更新它的显示ID;
关键代码如下所示:
// 返回item在ScrollView空间的坐标值 getPositionInView: function (item) { let worldPos = item.parent.convertToWorldSpaceAR(item.position); let viewPos = this.scrollView.node.convertToNodeSpaceAR(worldPos); return viewPos; }, // 每帧调用一次。根据滚动位置动态更新item的坐标和显示(所以spawnCount可以比totalCount少很多) update: function(dt) { this.updateTimer += dt; if (this.updateTimer < this.updateInterval) { return; // we don't need to do the math every frame } this.updateTimer = 0; let items = this.items; // 如果当前content的y坐标小于上次记录值,则代表往下滚动,否则往上。 let isDown = this.scrollView.content.y < this.lastContentPosY; // 实际创建项占了多高(即它们的高度累加) let offset = (this.itemTemplate.height + this.spacing) * items.length; let newY = 0; // 遍历数组,更新item的位置和显示 for (let i = 0; i < items.length; ++i) { let viewPos = this.getPositionInView(items[i]); if (isDown) { // 提前计算出该item的新的y坐标 newY = items[i].y + offset; // 如果往下滚动时item已经超出缓冲矩形,且newY未超出content上边界, // 则更新item的坐标(即上移了一个offset的位置),同时更新item的显示内容 if (viewPos.y < -this.bufferZone && newY < 0) { items[i].setPositionY(newY); let item = items[i].getComponent('Item'); let itemId = item.itemID - items.length; // update item id item.updateItem(i, itemId); } } else { // 提前计算出该item的新的y坐标 newY = items[i].y - offset; // 如果往上滚动时item已经超出缓冲矩形,且newY未超出content下边界, // 则更新item的坐标(即下移了一个offset的位置),同时更新item的显示内容 if (viewPos.y > this.bufferZone && newY > -this.content.height) { items[i].setPositionY(newY); let item = items[i].getComponent('Item'); let itemId = item.itemID + items.length; item.updateItem(i, itemId); } } } // 更新lastContentPosY和总项数显示 this.lastContentPosY = this.scrollView.content.y; this.lblTotalItems.string = "Total Items: " + this.totalCount; },
在此demo中,ScrollView列表显示的item其实是个按钮,而它是做为预制资源,其实可以在Creator中编辑成各种UI,并不局限于按钮形式。
最后,附上该Creator工程完整源代码的github地址:https://github.com/foupwang/CocosCreatorScrollViewDemo.git
相关文章推荐
- Android笔记-ListView总结(多选框ListViiew,动态加载,多线程更新ListView中的进度条)
- iOS开发学习笔记 -- (三)动态创建视图
- ios开发webview 的三种引用方式以及动态更新本地静态页的方法
- Android开发笔记-使用Handler机制更新UI的三种解决方案
- 开发笔记(不断更新中)
- Hibernate开发实践笔记--对象在set属性时更新了数据库问题
- 分布式应用系统服务器上下线动态感知程序开发学习笔记
- android开发中 如何动态更新TextView的内容?
- Android开发笔记之代码动态生成图片状态选择器
- Android应用开发笔记(12):Android应用的自动升级、更新模块的实现
- lua开发中的一些小笔记(持续更新)
- 苹果开发 笔记(56)下载zip文件到沙箱更新
- android 开发零起步学习笔记(十五):android: 静态XML和动态加载XML混合使用,以及重写Layout控件
- Android笔记-ListView总结(多选框ListViiew,动态加载,多线程更新ListView中的进度条)
- iPhone开发学习笔记002――Xib设计UITableViewCell然后动态加载
- android 开发零起步学习笔记(十):UI控件动态加载机制浅析
- 微信开发相关(动态更新)
- swift开发笔记19 在网络请求结束后更新UI
- Extjs 开发笔记【持续更新】
- Android开发初级阶段笔记(持续更新)