scrollView 优化

// Learn TypeScript:
//  - https://docs.cocos.com/creator/manual/en/scripting/typescript.html
// Learn Attribute:
//  - https://docs.cocos.com/creator/manual/en/scripting/reference/attributes.html
// Learn life-cycle callbacks:
//  - https://docs.cocos.com/creator/manual/en/scripting/life-cycle-callbacks.html


const {ccclass, property} = cc._decorator;

@ccclass
export default class scrollView extends cc.Component {

    /**显示区域 */
    private mView:cc.Node;
    /**承载区域 */
    private mContent:cc.Node;
    /**最大行数  根据宽高计算, 只有超出View时,向上取整 使得首尾可以兼顾 向上再取一个,防止出现空白*/
    private mMaxRow:number=0;
    /**是否开启滚动 */
    private mIsOpenScroll:boolean=false;
    /**最大列数 这个可以通过输入 或者传入决定 */
    private mMaxVer:number=1;
    /**最大替换的数量 */
    private mMaxItemCount:number=0;
    /**页面展示item的预制体元素 */
    private mItemPrfab:cc.Prefab;

    /**容器开始时的位置 */
    private mContentStartY:number;
    /**容器每次移动时的位置 */
    private mContentCurY:number;

    /**使用一个浮动指针,始终标记容器中显示在第一个节点的索引,
     * 默认为0(的时候,向下滚动,会回弹,所以指针值不做改变,
     * 值为最后一个数据节点索引时,向上滚动,会向下回弹,所以值也不做改变
     * 浮标指针只是用来取list中的数据使用
     * */
    private mPointer:number=0;

    private mListData:Array<any>=null;

    /**item的组件 */
    private mPfbComp:string=null;

    onLoad () {
        this.mView=cc.find("view",this.node);
        this.mContent=cc.find("view/content",this.node);
        this.mContentStartY=this.mView.height/2;


        this.addEvent();

    }
    protected onDestroy(): void {
        this.removeEvent();
    }

    private addEvent():void{
        this.node.on('scrolling', this.scrolling, this);
    }

    private removeEvent():void{
        this.node.off('scrolling', this.scrolling, this);
    }


    public init(list:any,pfb:cc.Prefab,comp:string,verCount:number=1):void{
        this.mListData=list;
        this.mItemPrfab=pfb;
        this.mMaxVer=verCount;
        this.mPfbComp=comp;

        
        //计算最大行数
        let needRow =Math.ceil(this.mListData.length/this.mMaxVer);
        let needHeight =needRow*this.mItemPrfab.data.height;
        if(needHeight>this.mView.height){
            this.mIsOpenScroll=true;
        }else{
            this.mIsOpenScroll=false;
        }
        this.mMaxRow=Math.ceil(this.mView.height/this.mItemPrfab.data.height)+1;
        this.mContent.height=needHeight;
        this.mMaxItemCount=this.mMaxRow*this.mMaxVer;
        this.initCount();

    }

    /**初始化容器节点 */
    private initCount():void{
        this.clearContent();
        this.mPointer=0;
        //根据列数,平分出N个单元。在每个单元中,将元素居中
        let col =this.mContent.width/this.mMaxVer;
        for(let i =0,varIndex=0;i<this.mMaxItemCount;i++,varIndex++){
            if(i>=this.mListData.length)return;
            varIndex%=this.mMaxVer;
            let item =cc.instantiate(this.mItemPrfab);
            this.mContent.addChild(item);
            item.x= (varIndex+0.5)*col-this.mContent.width/2;
            item.y=0-item.height*(Math.floor(i/this.mMaxVer)+0.5);
            let data= this.mListData[i];
            if(data){
                item.getComponent(this.mPfbComp)?.setData(this.mListData[i]);
            }
            item.active=!!data;    
        }

    }

    /**刷新容器节点位置 */
    private updataCount(changeY:number=0):void{
        let children =this.mContent.children,len=children.length;
        //显示区域的最顶层Y值
        let showTopY =this.mItemPrfab.data.height*0.5;
        //显示区域,最低层Y值
        let showBootomY =showTopY-this.mItemPrfab.data.height*this.mMaxRow;
        for(let i =0,varIndex=0;i<len;i++,++varIndex){
            let child =children[i];
            let sumY =child.y+changeY;
            varIndex%=this.mMaxVer;
            let data=null;
            if(sumY>=showTopY){
                data=this.mListData[(this.mMaxRow+this.mPointer-1)*this.mMaxVer+varIndex];
                //上边的移到下面
                if(data)child.getComponent(this.mPfbComp)?.setData(data);//
                child.y-=this.mMaxRow*this.mItemPrfab.data.height;
                child.active=!!data;
            }
            if(sumY<=showBootomY){
                //下面的移到上面
                data=this.mListData[this.mPointer*this.mMaxVer+varIndex];
                child.y+=this.mMaxRow*this.mItemPrfab.data.height;
                if(data)child.getComponent(this.mPfbComp)?.setData(data);
                child.active=!!data;
            }
    
        }

    }

    private scrolling():void{
        if(!this.mIsOpenScroll)return;
        this.mContentCurY=this.mContent.y;
        let changeY=this.mContentCurY-this.mContentStartY;
        //改变值小于0,说明,在往下拉,会触发回弹  大于容器高度的时候 说明是向上拉,也会触发回弹
        if(changeY<=0|| changeY>this.mContent.height-this.mView.height)return;
        //计算出,上下浮动的几个item高度的单位 向下取整,说明,只有完全出去,才算是浮标指针改变,指向下一个
        let pointCount =Math.floor(changeY/this.mItemPrfab.data.height) ;
        this.mPointer=pointCount;
        this.updataCount(changeY);
     }

     /**清理容器 */
     private clearContent():void{
        this.mContent.y=this.mContentStartY;
        this.mContent.removeAllChildren();

     }
}

纵向循环利用item ,优化scrollView 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值