CCVirtualGridList - Cocos Creator 虚拟列表

一 控件介绍

CCVirtualGridList是基于Cocos Creator ScrollView + Layout 编写的一个具有虚拟布局特点的滚动列表控制容器。支持平滑滚动显示大量数据对象,图片元素可以实现异步按帧加载保证滚动平滑具有滚动翻页功能自适应宽度显示多列单项选择局部更新等实用功能。

Cocos Creator 引擎中提供了一个常规的滚动控制容器——ScrollView,实现基本滚动控制。但是缺少与之配合的List控件来实现虚拟布局功能,需要开发者手动扩展,在这里就提供一个实现虚拟布局功能的扩展列表控件,是参照Egret中的List控件的接口方式来实现。


demo_screenshot_1.png

二 虚拟布局原理

虚拟布局的原理其实很简单,就是只加载和显示可视区域的列表内容,可视区域外的并没有实体控件被实例化。以滚动事件驱动,动态滚动并复用可视区域内的列表模板,切换数据显示,看上去像一个完整的列表在上下滚动,由于此种设计实例化控件少,所以内存占用极少,drawcall数量低而且稳定,所以现在被普遍应用。但是虚拟布局的核心不仅在于此,由于需要不停地切换显示内容,如何将素材转换的更快速,更平滑才是虚拟列表的关键。CCVirtualGridList在VirtualGridListBaseItem 中提供自己的加载图片的方法——loadImage,实现异步按帧加载,保证列表滚动流畅度,又能有效利用缓存。

三 VirtualGridList 使用

使用控件非常简单,只需要拷贝demo项目中三个文件VirtualGridList.prefab,VirtualGridList.js,VirtualGridListBaseItem.js 到您的工程中Prefabs文件夹中即可。使用之前将VirtualGridList.prefab拖入画面中, 列表单元控制组件继承 VirtualGridListBaseItem 就可以。

四 API说明

1. VirtualGridList 启动参数

启动参数可以在creator 图形化界面填入,但是为了不受预制体的维护影响,建议通过初 始化脚本接口传入启动参数。

virtualGridList.initGridList(itemTemplatePrefab, itemComponentName, options?)

参数

- itemTemplatePrefab    cc.Prefab   列表单元显示控件
- itemComponentName     String      列表单元显示控件控制器名称, 必须继承 VirtualGridListBaseItem
- options? {                     
    paddingTop?: Number             列表距离上边缘距离 默认为0
    paddingBottom?: Number          列表距离下边缘距离 默认为0
    spacingX?: Number               列间距 默认为3
    spacingY?: Number               行间距 默认为3
    columnNum?: Number              列数 默认为0,列数自动适配容器宽度
    useVirtualList?: Boolean        是否启用虚拟列表 默认为true
    emptyTip?: cc.String            没有数据显示提示
    cacheImage?: Boolean            通过virtualGridListBaseItem.loadImage()方法加载的
                                      图片,自动缓存,控件回收后,图片缓存将被全部释放。
}

2. VirtualGridList 功能接口

createItemsDisplayList(dataList: any[]): void

首次创建显示列表, dataList为数据数组

appendItemsToDisplayList(dataList: any[]): void

追加显示列表, dataList为追加的数据数组,适用于滚动翻页

getDataList(): any[]

获取数据数组

getTemplateItems(): cc.Prefab[]

获取显示对象列表

clearList(): void

清空列表

findItemDisplayByData(data: any): cc.Prefab

根据数据对象查找对应的显示对象,当开启虚拟列表的时候,返回对象可能不存在

getImageFromCache(key: String): cc.Texture2D

获取缓存图片

addScrollToBottomEventHandler(handler: Function, thisObj: any): void

注册滚动至底部回调方法 当useVirtualList=false 时不可用

refreshItemDisplays(some?: any[]): void

修改数据后,刷新列表显示,some代表指定刷新的对象, 不传则刷新全部。

isTop(): Boolean

判断是否滚动至顶部

scrollToTop(): void

滚动至顶部

scrollToFixedPosition(itemIndex: Number, sec?: Number): void

滚动到固定位置 itemIndex代表滚动至指定显示对象的索引, sec为滚动动画时长

3. VirtualGridListBaseItem 显示单元基类 (必须继承) 接口

data: any

数据对象。来自要显示的数据列表中的一条,每一条显示单元控件,都对应一条数据对象,当useVirtualLayout= true 的时候,单元控件对应的data数据对象不固定,会滚动切换。

dataChanged(): void

子类可覆盖方法,自定义显示方法,当滚动交替或初始化的时候触发。当useVirtualLayout= true 的时候,每一个显示单元控件都是滚动复用的,所以对应的Component组件也是复用的,所以不要在其内部记录与某一条数据对应的变量或属性。

dataChanged() {
        this._super();
        const data = this.data;
        this.loadImage(data.pic, this._showImg, this); // 建议所有图片通过loadImage加载,可以自动缓存,并且异步按帧加载,不卡顿
        this.lbItemName.getComponent(cc.Label).string = data.name;
        this.lbDate.getComponent(cc.Label).string = data.date;
    }

getItemIndex(): Number

获取现实对象在队列中的索引

onSelect(): void

子类可覆盖方法,点选触发事件,只支持单选

onUnselect(): void

子类可覆盖方法,如果当前为选中状态,当其他单元被点选触发此事件

onLeave(): void

子类可覆盖方法,当控件滑动离开可视区的时候触发 当useVirtualList=false 时不可用

onEnter(): void

子类可覆盖方法,当控件滑动进入可视区的时候触发 当useVirtualList=false 时不可用

loadImage(pic: String, cb: Function, thisObj: any): void

VirtualGridList 提供的异步加载图片, 自动缓存。pic: 图片地址, cb: 图片加载后的回调方法,thisObj: 回调方法this对象

五 显示列表

initGridList(){
        this._gridListController.initGridList(this.itemTemplate, 'ItemDisplayController', {
            paddingTop: 10,
            paddingBottom: 100,
            spacingY: 5,
            emptyTip: '什么也没有啊',
            columnNum: this._currentColumn,
            useVirtualList: true
        });
        this._gridListController.addScrollToBottomEventHandler(this._nextPage, this); //注册翻页事件

        this._showList();
    },
  showList(pageNo, itemCount) {
        pageNo = pageNo || 1;
        itemCount = itemCount || 29;
        let list = [];
        let total = pageNo * itemCount;
        let picIndex = 0;
        for (let i = (pageNo - 1) * itemCount + 1; i <= total; i++) {
            picIndex++;
            let item = {
                pic: "avatar/avatar_" + picIndex,
                date: "3/9 12:00",
                name: i + '_测试邮件'
            }
            list.push(item);
        }
        this._dataList = this._dataList ? this._dataList.concat(list) : list; // 滚动翻页需要合并数据数组

        this._gridListController.appendItemsToDisplayList(list);
    }
demo_screenshot_2.png

demo_screenshot_3.png

demo_screenshot_1.png

六 配合CCButtonDropdownList可以扩展实现带有虚拟布局的下拉列表

CCVirtualGridList 源码 + Demo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,440评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,814评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,427评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,710评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,625评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,014评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,511评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,162评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,311评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,262评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,278评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,989评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,583评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,664评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,904评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,274评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,856评论 2 339

推荐阅读更多精彩内容

  • 1,NSObject中description属性的意义,它可以重写吗?答案:每当 NSLog(@"")函数中出现 ...
    eightzg阅读 4,127评论 2 19
  • 废话不多说,直接上干货 ---------------------------------------------...
    小小赵纸农阅读 3,321评论 0 15
  • 1.badgeVaule气泡提示 2.git终端命令方法> pwd查看全部 >cd>ls >之后桌面找到文件夹内容...
    i得深刻方得S阅读 4,619评论 1 9
  • 窗外的风在怒吼着,从窗而入的风吹在脸上凉簌簌,很爽,牙疼貌似也因为风的吹拂感觉好一点了,在风的陪伴下我敲着今天的作...
    花缘过客阅读 324评论 0 0
  • 中国画的分类 1.山水画 山水画最早起源于秦汉,后来经过各个朝代的发展,各朝代主要代表性人物及作品如下: 2.人物...
    我是森森阅读 681评论 0 0