水友的一个循环列表(带下拉刷新,上拉加载)


cocos论坛原文地址:Cocos Creator ScrollView 性能优化之 UISuperScrollView 开箱即用

代码下载地址:https://github.com/icipiqkm/UISuperScrollView

demo下载

水友的循环列表

cocos也不提供这样的组件,自己写的列表没有下拉刷新和上拉加载功能,所以如果有项目要用到,直接用水友的好了。

水友的列表是继承cc.ScrollView扩展的,用法就是先创建一个cocos默认的scrollView,把scrollView节点上的cc.ScrollView删除,替换为UISuperScrollView

节点content挂上UISuperLayout,这是用于布局。具体使用得看github上demo。

一个普通垂直列表

按着demo自己实现一个普通垂直列表,注意到几个问题:

1 item创建倍率问题

如下图,在item创建倍率默认2情况下,能看见的item是8个,但是创建的item是15个,有很多item都是浪费的。

所以设置item倍率为1.2,这样会减少创建多余的item。例如下图,下拉列表效果不变的情况下,ListItem只有10个。

2 RefreshItemEvents 刷新事件问题

默认刷新事件是在属性面板中设置的

我习惯在代码里监听,所以将RefreshItemEvents属性去掉了,改为代码里监听

UISupserLayout.ts:

一个普通垂直列表的代码Vertical.ts:

/**
 * 垂直列表
 */
@ccclass
export default class Vertical extends cc.Component {

    @property({ type: UISpuerScrollView, tooltip: "列表scrollView" })
    scrollView: UISpuerScrollView = null;
    @property({ type: UISuperLayout, tooltip: "列表layout" })
    layout: UISuperLayout = null;

    private testList = [
        { id: 0, msg: "1" },
        { id: 1, msg: "1" },
        { id: 2, msg: "1" },
        { id: 3, msg: "1" },
        { id: 4, msg: "1" },
        { id: 5, msg: "1" },
        { id: 6, msg: "1" },
        { id: 7, msg: "1" },
        { id: 8, msg: "1" },
        { id: 9, msg: "1" },
        { id: 10, msg: "1" },
        { id: 11, msg: "1" },
        { id: 12, msg: "1" },
        { id: 13, msg: "1" },
        { id: 14, msg: "1" },
        { id: 15, msg: "1" },
    ]

    onLoad() {
        this.layout.node.on(UISuperLayout.REFRESH_ITEM, this.refreshItem, this);
        this.layout.total(this.testList.length);
    }

    /**数据更新 */
    private refreshItem(node: cc.Node, index: number) {
        node.getComponent(ListItem).dataChanged(this.testList[index]);
    }
}

一个普通的水平列表

只要选择UISuperScrollView和UISuperLayout的Horizontal就行了。

一个普通的网格列表

网格列表不需要像cc.ScrollView那样选择Grid布局,而是设置UISuperLayout的每组item个数

例如上图的网格布局,每列3个item。

一个普通的向上循环

向上或向下循环,勾选UISuperLayout的头部滑动循环和尾部滑动循环就行。

但是这个循环功能是有问题的,如上图列表最长是29,向上显示到0以后,理论上是从29接着循环,实际是从10开始接着循环。

 上拉和下拉事件

UI显示方面,在view节点下放上head和foot两个文本,用于显示刷新状态。

head和foot节点的高度必须和UISuperScrollView的顶部偏移量和底部偏移量一致。例如下图中设置为50,那么head和foot节点也必须是50,代码中根据这个值来控制刷新时content的位置。

触发下拉事件的条件是滚动容器滑动距离超过:顶部偏移量*满足触发Header的倍数,如下图就是50*2=100,下拉滑动超过100像素就会触发下拉事件。

水友使用属性面板中来绑定事件的,我改成了在代码中绑定。

我修改了源码,让上拉和下拉事件在代码中监听:

this.scrollView.node.on(UISpuerScrollView.PULL_DOWN, this.pullDown, this);
this.scrollView.node.on(UISpuerScrollView.PULL_UP, this.pullUp, this);

//下拉事件
private pullDown(event: UISuperHeaderAndFooterEvent){

}

//上拉事件
private pullUp(event: UISuperHeaderAndFooterEvent){

}

触发上拉或下拉事件后,需要加载数据并刷新列表,并显示加载和刷新的进度,这些操作需要根据event的值来进行,event意义如下:

完整代码:

import UISuperLayout from "../../src/UISuperLayout";
import UISpuerScrollView, { UISuperHeaderAndFooterEvent } from "../../src/UISuperScrollView";
import ListItem from "../common/ListItem";

const { ccclass, property } = cc._decorator;

@ccclass
export default class Refresh extends cc.Component {

    @property({ type: UISpuerScrollView, tooltip: "列表scrollView" })
    scrollView: UISpuerScrollView = null;
    @property({ type: UISuperLayout, tooltip: "列表layout" })
    layout: UISuperLayout = null;

    @property({ type: cc.Node, tooltip: "头部文字根节点" })
    head: cc.Node = null;
    @property({ type: cc.Node, tooltip: "底部文字根节点" })
    foot: cc.Node = null;
    @property({ type: cc.Label, tooltip: "头部文字" })
    headLab: cc.Label = null;
    @property({ type: cc.Label, tooltip: "底部文字" })
    footLab: cc.Label = null;

    private testList = [];

    onLoad() {
        for (let i = 0; i < 2; i++) {
            this.testList.push({ id: i, msg: i + "" });
        }

        this.head.scaleY = 0;
        this.foot.scaleY = 0;

        this.layout.node.on(UISuperLayout.REFRESH_ITEM, this.refreshItem, this);
        this.scrollView.node.on(UISpuerScrollView.PULL_DOWN, this.pullDown, this);
        this.scrollView.node.on(UISpuerScrollView.PULL_UP, this.pullUp, this);
        this.layout.total(this.testList.length);
    }

    /**数据更新 */
    private refreshItem(node: cc.Node, index: number) {
        node.getComponent(ListItem).dataChanged(this.testList[index]);
    }

    /**下拉事件 */
    private pullDown(event: UISuperHeaderAndFooterEvent) {
        //文字显示
        if (event.progressStage == "wait") {
            this.headLab.string = "下拉刷新";
            this.head.scaleY = 1;
        } else if (event.progressStage == "lock") {
            this.headLab.string = "刷新中";
        }
        //执行刷新操作
        if (event.action == true) {
            for (let i = 0; i < 2; i++) {
                this.testList.unshift({ id: i, msg: "新增:" + i });
            }
            this.layout.total(this.testList.length);
        }
        //隐藏文字显示
        if (event.action == false && event.progressStage == "release" && event.progress <= 1) {
            this.head.scaleY = 0;
        }
    }

    /**上拉事件 */
    private pullUp(event: UISuperHeaderAndFooterEvent) {
        //文字显示
        if (event.progressStage == "wait") {
            this.footLab.string = "上拉刷新";
            this.foot.scaleY = 1;
        } else if (event.progressStage == "lock") {
            this.footLab.string = "刷新中";
        }
        //执行刷新操作
        if (event.action == true) {
            for (let i = 0; i < 2; i++) {
                this.testList.push({ id: i, msg: "新增:" + i });
            }
            this.layout.total(this.testList.length);
        }
        //隐藏文字显示
        if (event.action == false && event.progressStage == "release" && event.progress <= 1) {
            this.foot.scaleY = 0;
        }
    }
}

搜索

复制