scrollview 优化扩展

论坛上的关于scrollview的列表优化有很多文章,这边提供一个新思路,用于在子节点尺寸不同情况下的使用方案

先定义子节点组件一个虚函数 setVisible


@ccclass("ScrollViewExItem")
export abstract class ScrollViewExItem extends Component {
    abstract setVisible(b: boolean);
}

定义scrollview扩展持有 子节点列表


@ccclass("ScrollViewEx")
@requireComponent(cc.ScrollView)
@menu("tools/ScrollViewEx")
export default class ScrollViewEx extends Component {
    _scrollview: cc.ScrollView;
    _skeList: ScrollViewExItem[] = [];
    onLoad() {
        this._scrollview = this.node.getComponent(cc.ScrollView);
    }

    walk<T extends ScrollViewExItem>(comp: new (...args: any[]) => T) {
        this._skeList = [];
        this._scrollview.content.walk(
            (node: cc.Node) => {
                let c_sp = node.getComponent(comp);
                if (c_sp) {
                    this._skeList.push(c_sp);
                }
            },
            (node: cc.Node) => {}
        );

        this.onScroll();
    }

    protected onEnable(): void {
        this._scrollview.node.on(cc.ScrollView.EventType.SCROLLING, this.onScroll, this);
        this.node.on(
            cc.Node.EventType.SIZE_CHANGED,
            () => {
                this.scheduleOnce(() => {
                    this.onScroll();
                });
            },
            this
        );
    }

    protected onDisable(): void {
        this._scrollview.node.off(cc.ScrollView.EventType.SCROLLING, this.onScroll, this);
    }

    onScroll() {
        if (!cc.isValid(this._scrollview.node)) {
            return;
        }
        let viewRect = cc.rect(
            0,
            -this._scrollview.node.getComponent(cc.UITransform).height / 2,
            this._scrollview.node.getComponent(cc.UITransform).width,
            this._scrollview.node.getComponent(cc.UITransform).height / 2
        );
        for (let skeNode of this._skeList) {
            if (!cc.isValid(skeNode.node)) {
                return;
            }
            let curPos = this._scrollview.node
                .getComponent(cc.UITransform)
                .convertToNodeSpaceAR(skeNode.node.getComponent(cc.UITransform).convertToWorldSpaceAR(cc.v3(0, 0)));
            let curRect = cc.rect(
                curPos.x - skeNode.node.getComponent(cc.UITransform).width / 2.0,
                curPos.y - skeNode.node.getComponent(cc.UITransform).height / 2.0,
                skeNode.node.getComponent(cc.UITransform).width,
                skeNode.node.getComponent(cc.UITransform).height
            );

            skeNode.setVisible(viewRect.intersects(curRect));
        }
    }

    onDestroy() {
        this._skeList.length = 0;
    }
}

目的是通过子节点的大小,用矩形检测来达到控制显隐的目的

子节点集成scrollviewExItem之后,重写setVisible 方法达到控制的目的

scrollViewEx 通过walk函数来激活 ,具体示例在游戏列表scrollViewEx中

This article was updated on 九月 29, 2024