邮箱、排行榜、好友列表等功能怎样实现循环加载,分页加载,已实现多行多列

邮箱、排行榜等功能怎样实现循环加载,分页加载,已实现多行多列

  • 功能介绍:
    在游戏中,经常会有邮箱,排行榜,好友列表等需要加载大量数据的功能,这个时候,就需要开发人员为游戏的性能考虑使用的方法,在此,做游戏前端开发三年的小菜鸟程序媛奉上自己的代码,供小伙伴们参考和批评~~~

  • 代码实现背景:
    引擎:CocosCreator v1.9.0
    语言:TypeScript

废话不多说,直接上代码啦~~~~~
BaseScrollView.ts核心代码如下…

import UIManager from "../UIManager";
import ToolsMgr, { LogType } from "../FrameWork/ToolsMgr";

const {ccclass, property} = cc._decorator;

@ccclass
export default class BaseScrollView extends cc.ScrollView {

    //item释放池
    itemPool : cc.NodePool = null;

    //item预制体
    @property(cc.Prefab)
    itemPerfab : cc.Prefab = null;

    @property({ tooltip: "是否是垂直滚动" } || cc.Boolean)
    _horizontal: boolean = false;

    @property({ tooltip: "是否是垂直滚动" })
    set horizontal(value) {
        this._horizontal = value;
        this._vertical = !value;
    }
    @property({ tooltip: "是否是垂直滚动" })
    get horizontal() {
        return this._horizontal;
    }

    @property({ tooltip: "是否是水平滚动" } || cc.Boolean)
    _vertical: boolean = true;

    @property({ tooltip: "是否是水平滚动" })
    set vertical(value) {
        this._horizontal = !value;
        this._vertical = value;
    }

    @property({ tooltip: "是否是水平滚动" })
    get vertical() {
        return this._vertical;
    }

    /// 缓冲加载添加的变量 
    //item间隔
    @property(cc.Float)
    spacing : number = 0;

    //创建的itemList
    createItemList : cc.Node[] = [];

    //创建的itemDataList
    createItemDataList : any[] = [];

    //数据List
    dataList : any[] = [];

    //数据的最大数量
    maxCount : number = 0;

    //item创建的最大数量
    @property(cc.Integer)
    curMaxCount : number = 5;

    //每一个item的高度
    @property(Number)
    itemHeight : number = 0;

    //每一个item的宽度
    @property(Number)
    itemWidth : number = 0;

    viewCal : number = 0;

    lastContentPosition: cc.Vec2 = cc.v2(0, 0);

    Vec2SVV : cc.Vec2 = cc.p(0, 0);

    Vec2SVH : cc.Vec2 = cc.p(0, 0);

    // 多行多列 
    @property(Number)
    moreNum : number = 1;

    tempV : number = 0;
    tempH : number = 0;
    /// 多行多列 ///
    
    /// 分页请求数据 ///
    changePageCallBack : Function = null;

    // 每页显示的请求数据的位置(**比如:当前每页数据量为20,想在第15条的时候,请求下一页的数据,这块就是20 - 15 = showPagePos )
    @property(Number)
    showPagePos : number = 0;

    // 分页提示“正在加载中。。。”的UI
    @property(cc.Node)
    loadingTips : cc.Node = null;

    //数据的最大数量
    maxTopNum : number = 0;

    //当前翻得页数
    curPage : number = 0;

    // 防止在弱网情况下,多次请求相同数据
    requestData : boolean = false;

    /// 分页请求数据 ///
    
    ///
    onLoad(){
        this.Init();
    }

    /**
     * 初始化释放池
     */
    Init(){
        this.itemPool = new cc.NodePool();
    }

    /**
     * 创建节点item
     * @param data 相关榜单的数据
     */
    CreateItem() : cc.Node {
        let item : cc.Node = null;
        if(this.itemPerfab != null)
        {
            (this.itemPool.size() > 0) ? (item = this.itemPool.get()) : (item = cc.instantiate(this.itemPerfab));
        }
        else
        {
            ToolsMgr.Get().printAllLog("leaderboard itemPerfab is null!!", LogType.info);
        }
        return item;
    }

    // 清空
    Clear()
    {
        this.ClearItemList();
        
        if (!this.itemPool)
            return;
        while(this.itemPool.size() > 0)
        {
            let node = this.itemPool.get();
            if (!node || !cc.isValid(node))
                continue;
            node.destroy();
            node = null;
        }
    }

    ClearItemList()
    {
        if (this.createItemList)
        {
            for(let i = 0; i < this.createItemList.length; ++i)
            {
                let node = this.createItemList[i];
                if (!node || !cc.isValid(node))
                    continue;
                node.removeFromParent(false);
                this.createItemDataList[i].Release();
                // node.getComponent(this.itemPerfab.name).Release();
                node.active = false;
                this.itemPool.put(node);
            }
        }
        this.createItemList = [];
        this.createItemDataList = [];
    }

    /**
     * 
     * @param dataList 分页加载时的第一页数据 或者 不是分页加载时的所有数据
     * @param closeBack 分页加载时的回调函数,用来返回下一个页数,并向服务器请求数据
     * @param maxTopNum 当前数据可显示的最大数据量
     * @param curPage 当前页数
     */
    initCellDataList(dataList : any[], closeBack ?: Function, maxTopNum ?: number, curPage ?: number){
        this.stopAutoScroll();
        this.dataList = dataList;
        this.createCellList();
        if (closeBack) this.changePageCallBack = closeBack;
        if (maxTopNum) this.maxTopNum = maxTopNum;
        if (curPage) this.curPage = curPage;
    }

    /**
     * 
     * @param dataList 分页加载时,每一页请求回来的数据
     * @param curPage 分页加载时,当前页数
     */
    addDataList(dataList : any[], curPage ?: number){
        this.showLoadingTips(false);
        this.requestData = false;

        if(curPage) this.curPage = curPage;
        dataList.forEach(data =>{
            this.dataList.push(data);
        });
        this.refreshOnload();
    }

    /**
     * 创建itemList列表,记下当前数据的最大量
     */
    private createCellList(){
        this.content.height = this.content.parent.height;
        this.content.width = this.content.parent.width;
        this.ClearItemList();
        this.maxCount = this.dataList.length;
        if(this._vertical){
            this._VerticalOnLoad();
            this._createVerticalCellList();
        }else{
            this._HorizontalOnLoad();
            this._createHorizontalCellList();
        }
    }

    /**
     * 刷新最大值,重新计算可视范围
     */
    private refreshOnload(this){
        this.maxCount = this.dataList.length;
        if(this._vertical){
            this._VerticalOnLoad();
        }else{
            this._HorizontalOnLoad();
        }
    }

    private _VerticalOnLoad(this){
        this.content.setAnchorPoint(cc.p(0.5, 1));
        this.viewCal = this.curMaxCount * (this.itemHeight + this.spacing) / 2;
        if(this.maxCount % this.moreNum == 0){
            this.content.height = this.maxCount / this.moreNum * (this.itemHeight + this.spacing);
        }else{
            this.content.height = (Math.floor(this.maxCount / this.moreNum) + 1) * (this.itemHeight + this.spacing);
        }
    }

    private _HorizontalOnLoad(){
        this.content.setAnchorPoint(cc.p(0, 0.5));
        this.viewCal = this.curMaxCount * (this.itemWidth + this.spacing) / 2;
        if(this.maxCount % this.moreNum == 0){
            this.content.width = this.maxCount / this.moreNum * (this.itemWidth + this.spacing);
        }else{
            this.content.width = (Math.floor(this.maxCount / this.moreNum) + 1) * (this.itemWidth + this.spacing);
        }
    }

    private _createVerticalCellList(){
        if((this.curMaxCount -2) * this.itemHeight > this.content.parent.height){
            UIManager.Get().CreatePromptLable("填写的curMaxCount参数大于数据的最大值,请修改!");
            ToolsMgr.Get().printAllLog("填写的curMaxCount参数大于数据的最大值,请修改!" + (this.curMaxCount -1) * this.itemHeight + "------" + this.content.parent.height, LogType.info);
            return;
        }

        this.tempV = (this.spacing + this.itemWidth) / 2;
        let temp = this.moreNum - 1;
        /**
         * 为防止滑动到一半的时候会导致切换页面时,获取到的数据是前几个,
         * 而当前位置的数据没有刷新,所以在切换页面的时候,直接跳到初始位置
         */
        if(this.content.parent.getAnchorPoint().x == 0.5 && this.content.parent.getAnchorPoint().y == 0.5){
            this.Vec2SVV = cc.p(this.content.parent.x, this.content.parent.height / 2);
        }
        this.setContentPosition(this.Vec2SVV);

        //根据数据创建所有的item
        for(var i = 0; i < this.dataList.length; i++){
            if(i > this.curMaxCount * this.moreNum - 1){
                return;
            }
            var item = this.CreateItem();
            item.active = true;
            this.content.addChild(item);
            this.createItemList.push(item);
            item["CellID"] = i;
            this.createItemDataList.push(item.getComponent(this.itemPerfab.name));
            this.createItemDataList[i].SetData(this.dataList[i]);
            if( i !== 0 && ( i % this.moreNum === 0 )){
                temp = this.moreNum - 1;
            }else if(i !== 0 && ( i % this.moreNum !== 0 )){
                temp = temp - 2;
            }
            let y = -item.height * (0.5 + Math.floor(i / this.moreNum)) - this.spacing * (Math.floor(i / this.moreNum) + 1);
            item.setPosition( -this.tempV * (temp), y);
        }
    }

    private _createHorizontalCellList(){
        if((this.curMaxCount -2) * this.itemWidth > this.content.parent.width){
            UIManager.Get().CreatePromptLable("填写的curMaxCount参数大于数据的最大值,请修改!");
            ToolsMgr.Get().printAllLog("填写的curMaxCount参数大于数据的最大值,请修改!" + (this.curMaxCount -1) * this.itemWidth + "------" + this.content.parent.width, LogType.info);
            return;
        }

        this.tempH = (this.spacing + this.itemHeight) / 2;
        let temp = this.moreNum - 1;

        if(this.content.parent.getAnchorPoint().x == 0.5 && this.content.parent.getAnchorPoint().y == 0.5){
            this.Vec2SVH = cc.p(-this.content.parent.width / 2, this.content.parent.y);
        }
        
        this.setContentPosition(this.Vec2SVH);
        //根据数据创建所有的item
        for(var i = 0; i < this.dataList.length; i++){
            if(i > this.curMaxCount * this.moreNum - 1){
                return;
            }
            var item = this.CreateItem();
            item.active = true;
            this.content.addChild(item);
            this.createItemList.push(item);
            item["CellID"] = i;
            this.createItemDataList.push(item.getComponent(this.itemPerfab.name));
            this.createItemDataList[i].SetData(this.dataList[i]);
            if( i !== 0 && ( i % this.moreNum === 0 )){
                temp = this.moreNum - 1;
            }
            if(i !== 0 && ( i % this.moreNum !== 0 )){
                temp = temp - 2;
            }
            // 父节点content的Anchor坐标是(0, 0.5),所以node的y坐标是负值
            let x = item.width * (0.5 + Math.floor(i / this.moreNum)) + this.spacing * Math.floor(i / this.moreNum);
            item.setPosition(x, this.tempH * (temp));
        }
    }

    private getPosView(item : cc.Node){
        let worldPos = item.parent.convertToWorldSpaceAR(item.getPosition());
        let viewPos = this.node.convertToNodeSpaceAR(worldPos);
        return viewPos;
    }

    private scrollEvent(sender, event){
        if(this._vertical){
            this._updateVerticalContentView();
        }else{
            this._updateHorizontalContentView();
        }
    }

    private _updateVerticalContentView(){
        let isDown = this.content.y < this.lastContentPosition.y;
        let offsetY = (this.itemHeight + this.spacing) * (this.createItemList.length / this.moreNum);
        let newY = 0;

        for(var i = 0; i < this.createItemList.length; i++){
            let viewPos = this.getPosView(this.createItemList[i]);
            if(isDown){     // 数据的值变小
                newY = this.createItemList[i].y + offsetY;
                if (viewPos.y < -(this.viewCal) && newY < 0){
                    let item = this.createItemDataList[i];
                    let itemIdx = this.createItemList[i]["CellID"];
                    let idx = Number(itemIdx) - this.createItemList.length;
                    if (idx < 0)
                        continue;
                    this.createItemList[i].y = newY;
                    this.createItemList[i].x = viewPos.x;
                    if(item){
                        item.SetData(this.dataList[idx]);
                    }

                    this.createItemList[i]["CellID"] = idx;
                }
            }else{          // 数据的值变大
                newY = this.createItemList[i].y - offsetY;
                if (viewPos.y > this.viewCal && newY > -this.content.height){
                    let item = this.createItemDataList[i];
                    let itemIdx = this.createItemList[i]["CellID"];
                    let idx = Number(itemIdx) + this.createItemList.length;
                    if (idx >= this.dataList.length)
                        continue;
                    this.createItemList[i].y = newY;
                    this.createItemList[i].x = viewPos.x;
                    if(item){
                        item.SetData(this.dataList[idx]);
                    }
                    
                    if(this.changePageCallBack) this.changePage(idx);

                    this.createItemList[i]["CellID"] = idx;
                }
            }
        }
        this.lastContentPosition = this.content.position.clone();
    }
    
    private _updateHorizontalContentView(){
        let isLeft = this.content.x < this.lastContentPosition.x;
        let offsetX = (this.itemWidth + this.spacing) * (this.createItemList.length / this.moreNum);
        let newX = 0;

        for (var i = 0; i < this.createItemList.length; i++) {
            let viewPos = this.getPosView(this.createItemList[i]);
            if (isLeft) {
                newX = this.createItemList[i].x + offsetX;
                if (viewPos.x < -this.viewCal && newX < this.content.width) {
                    let item = this.createItemDataList[i];
                    let itemIdx = this.createItemList[i]["CellID"];
                    let idx = Number(itemIdx) + this.createItemList.length;
                    if (idx >= this.dataList.length)
                        continue;
                    this.createItemList[i].x = newX;
                    this.createItemList[i].y = viewPos.y;
                    if(item){
                        item.SetData(this.dataList[idx]);
                    }

                    this.createItemList[i]["CellID"] = idx;
                }
            } else {
                newX = this.createItemList[i].x - offsetX;
                if (viewPos.x > this.viewCal && newX >= 0) {
                    let item = this.createItemDataList[i];
                    let itemIdx = this.createItemList[i]["CellID"];
                    let idx = Number(itemIdx) - this.createItemList.length;
                    if (idx < 0)
                        continue;
                    this.createItemList[i].x = newX;
                    this.createItemList[i].y = viewPos.y;
                    if(item){
                        item.SetData(this.dataList[idx]);
                    }

                    this.changePage(idx);

                    this.createItemList[i]["CellID"] = idx;
                }
            }
        }
        this.lastContentPosition = this.content.position.clone();
    }

    changePage(idx : number){
        try
        {
            if(!this.changePageCallBack)
                return;
            if (this.requestData)
                return;
            let page = this.dataList.length - this.showPagePos;
            if(idx >= this.showPagePos && idx == page && this.dataList.length < this.maxTopNum){
                // this.loadingTips.setPositionY(-this.loadingTips.parent.height / 2 + this.loadingTips.height / 2);
                if((this.curPage + 1) != 1){
                    this.showLoadingTips(true);
                }
                this.requestData = true;
                this.changePageCallBack(this.curPage + 1);
            }
        }
        catch(e)
        {
            cc.error("BaseScrollView:changePage catch err " + e.message);
        }
    }
    showLoadingTips(isShow : boolean){
        if(this.loadingTips) this.loadingTips.active = isShow;
    }
}
  • 代码块的使用方法:

    changePageCallBack(curPage : number){
         ToolsMgr.Get().printAllLog("数值在变大。。。。:", LogType.info);
         LeaderboardLayer.curPage = curPage;
         LeaderboardModel.Get().RequestData(LeaderboardLayer.curListType, LeaderboardLayer.curPage);
     }
    RefreshSV(dataList : Array<any>, maxTopNum : number, curPage ?: number){
         this.scrollView.stopAutoScroll();
         this.scrollView.getComponent(BaseScrollView).initCellDataList(dataList, this.changePageCallBack, maxTopNum, curPage);
     }
    

在需要使用循环加载或者分页加载的节点上的ScrollView组件移除,并将BaseScrollView脚本挂上去,然后设置参数如下:
在这里插入图片描述

在这里插入图片描述
注意:
1、ScrollEvents要设置
2、itemPerfab : 循环加载的itemPerfab,Perfab的名字一定要跟Perfab所挂的脚本的名字一致,这个没想到解决办法,有更好方法的小伙伴,可以给我留言哦~~~
3、CurMaxCount:当前可视范围内可显示的最大的item数量
4、itemHeight:itemPerfab的高度
5、itemWidth:itemPerfab的宽度
6、MoreNum:多行多列时使用的数据,默认为1
7、ShowPagePos:在什么位置进行下一页数据的加载
(比如:当前每页数据量为20,想在第15条的时候,请求下一页的数据,这块就是20 - 15 = showPagePos)
8、LoadingTips:分页加载时,“加载中。。。”的tips的UI

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Freedom_of_a_cat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值