cocos creator实例--CocosCreator自封装列表组件ListComponent | 附代码

烈酒焚心 提交于 2019-12-16 10:44:08

使用场景 

      游戏中经常会做列表类型的功能,例如游戏记录、排行榜,涉及到的数据很多,如果使用自带的ScrollView,会需要创建很多列表项组件,效率会很低,也很影响性能,由于工作中使用到的比较多,就封装了一个组件ListComponent,大致实现原理如下:

  1. 在列表可见区域内,创建列表项Unit,列表项多余可见区+1;
  2. 设置需要更新的数据,保存在组件内,一开始从第一条开始显示,直到显示能显示的列表项;
  3. 滑动列表项,更新不断的更改列表项的位置和内容,从而实现滑动的效果。

 

存在问题

也有一些问题,如:

  1. 滑动太快会不流畅,所以组件内取消了弹性功能;
  2. 进度条的长度动态计算没有加入,所以取消了进度条的显示;

 

 

组件使用

具体使用步骤如下:

  1. 把ListComponent挂在到ScrollView组件上,如下图所示:
  2. 列表项的预制和列表项预制上负责更新的脚本名称设置好;
  3. 预制脚本需要添加reloadUI(data:any)方法,为了更新UI。

 

下图就是挂在脚本的效果:

 

下图是自己项目的更新UI的函数:

       这里根据自己的需要更新UI就行,传进来的data是一个对象类型的数据结构。

 

       功能模块使用起来也很简单,如ScrollView组件的名称为list,使用方法如下:

let data = [{name:'aa', age:1}, {name:'bb', age:2}];let listCom = list.getComponent('ListComponent');listCom .reloadData(data);listCom reloadUI();

 

最终实现效果如下图:

 

// Learn TypeScript:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/typescript.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/reference/attributes.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - [Chinese] https://docs.cocos.com/creator/manual/zh/scripting/life-cycle-callbacks.html
//  - [English] http://www.cocos2d-x.org/docs/creator/manual/en/scripting/life-cycle-callbacks.html

const {ccclass, property} = cc._decorator;

@ccclass
export default class ListComponent extends cc.Component {
    @property(cc.Prefab)
    prefabUnit: cc.Prefab = null;

    @property
    UnitComName: string = '';

    private mData: Array<any> = [];
    private mUnitHeight: number = 0;
    private mMaxCount: number = 0;
    private mCells: Array<any> = [];
    private mIdx: number = 0;
    private mOnBounceBottomCallback: any = null;
    private mOnUnitClickCallback: any = null;
    private mInited: boolean = false;

    // LIFE-CYCLE CALLBACKS:

    // onLoad () {}

    start () {

    }

    // update (dt) {}

    reloadData(data: Array<any>){
        this.mData = data;
    }

    reloadUI(){
        if(!this.mInited){
            this.initScrollView();
            this.addPrefab();
            this.mInited = true;
        }

        this.reload();
    }

    setOnBounceBottomCallback(callback: any){
        this.mOnBounceBottomCallback = callback;
    }

    setUnitClickCallback(callback: any){
        this.mOnUnitClickCallback = callback;
    }

    initScrollView(){
        if(this.prefabUnit == null){
            return;
        }

        let scrollView = this.node.getComponent(cc.ScrollView);
        if(scrollView == null){
            return;
        }
        
        scrollView.inertia = false;

        this.mUnitHeight = this.prefabUnit.data.height;
        this.mMaxCount = Math.floor(scrollView.node.height / this.mUnitHeight) + 2;

        if(this.mData.length > this.mMaxCount){
            scrollView.content.height = this.mMaxCount * this.mUnitHeight;
        }else{
            scrollView.content.height = this.mData.length * this.mUnitHeight;
        }

        scrollView.node.on("scrolling", this.onScrolling, this);
        scrollView.node.on("bounce-bottom", this.onBounceBottom, this);
        scrollView.scrollToTop(0);
    }

    addPrefab(){
        let scrollView = this.node.getComponent(cc.ScrollView);
        if(scrollView == null){
            return;
        }

        this.mCells = [];
        scrollView.content.removeAllChildren();
        for(let i = 0; i < this.mMaxCount; i++){
            let node = cc.instantiate(this.prefabUnit);            
            scrollView.content.addChild(node);
            node.x = node.width * (node.anchorX - 0.5);
            node.y = -node.height * (1 - node.anchorY) - node.height * i;
            this.mCells.push(node);

            let js = node.getComponent(this.UnitComName);
            if(js != null && js.registClickCallback != null){
                js.registClickCallback((idx, node) => {
                    this.onUnitClick(idx, node)
                });
            }
        }
    }

    onUnitClick(idx:number, node: cc.Node){
        if(this.mOnUnitClickCallback != null){
            this.mOnUnitClickCallback(idx, node);
        }
    }

    onScrolling(event){
        let offset = event.getScrollOffset();

        if(offset.y <= 0 && this.mIdx > 0){
            // 上移一格
            offset.y += this.mUnitHeight;
            event.scrollToOffset(offset);

            // 更新数据
            this.mIdx--;
            this.reload();
        }
        else if(offset.y >= event.getMaxScrollOffset().y && (this.mIdx < this.mData.length - this.mMaxCount)){
            // 下移一格
            offset.y -= this.mUnitHeight;
            event.scrollToOffset(offset);

            // 更新数据            
            this.mIdx++;
            this.reload();

            if(this.mIdx == this.mData.length - this.mMaxCount - 1){
                this.onBounceBottom(null);
            }
        }
    }

    onBounceBottom(event){
        if(this.mOnBounceBottomCallback != null){
            this.mOnBounceBottomCallback();
        }
    }

    reload(){
        for(let i = 0; i < this.mCells.length; i++){
            this.mCells[i].active = (i < this.mData.length);
            this.reloadCell(this.mIdx + i, this.mCells[i]);
        }
    }

    reloadCell(idx, scrollViewCell){
        if(idx < 0 || idx >= this.mData.length){
            return;
        }

        if(scrollViewCell == null || this.UnitComName == ''){
            return;
        }

        let UnitCom = scrollViewCell.getComponent(this.UnitComName);
        if(UnitCom != null && UnitCom.reloadUI != null){
            UnitCom.reloadUI(this.mData[idx]);
            scrollViewCell.attr({_idx_: idx});
        }
    }
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!