虚拟列表补充商店描述

开贴补充 虚拟列表 商店描述,介绍一下组件接口


YXIndexPath

/**
 * 表示索引的对象
 */
export declare class YXIndexPath extends ValueType {
    static ZERO: Readonly<YXIndexPath>;
    section: number;
    item: number;
    constructor(section: number, item: number);
}

YXEdgeInsets

/**
 * 表示边距的对象
 */
export declare class YXEdgeInsets extends ValueType {
    static ZERO: Readonly<YXEdgeInsets>;
    top: number;
    left: number;
    bottom: number;
    right: number;
    constructor(top: number, left: number, bottom: number, right: number);
}

YXCollectionViewCell

用来监听节点的重用状态

/**
 * @see NodePool.poolHandlerComp
 * 节点的自定义组件可以通过这个接口跟 @NodePool 的重用业务关联起来
 */
export interface YXCollectionViewCell extends Component {
    unuse(): void;
    reuse(args: any): void;
}

YXCollectionView

列表组件,负责接收数据,按照 YXLayout 规则排列节点,管理节点

/**
 * 列表组件
 */
export declare class YXCollectionView extends Component {
    /**
     * 版本号
     */
    static get VERSION(): string;
    /**
     * 滚动视图组件
     */
    get scrollView(): ScrollView;
    /**
     * 自动给挂载节点添加 mask 组件
     */
    mask: boolean;
    /**
     * 允许手势滚动
     */
    scrollEnabled: boolean;
    /**
     * 每多少帧刷新一次可见节点,1 表示每帧都刷
     */
    frameInterval: number;
    /**
     * 是否在滚动过程中立即回收不可见节点,默认 true
     * @bug 滚动过程中如果实时的回收不可见节点,有时候会收不到 scroll view 的 cancel 事件,导致 scroll view 的滚动状态不会更新 (且收不到滚动结束事件)
     * @fix 当这个属性设置为 false 时,只会在 `touch-up` 和 `scroll-ended` 里面回收不可见节点
     */
    immediateAutoRecycleInvisibleNodes: boolean;
    /**
     * 内容要分几个区展示,默认 1
     * 没有分区展示的需求可以不管这个配置
     */
    numberOfSections: number | ((collectionView: YXCollectionView) => number);
    /**
     * 每个区里要展示多少条内容
     */
    numberOfItems: number | ((section: number, collectionView: YXCollectionView) => number);
    /**
     * 注册 cell
     * 可多次注册不同种类的 cell,只要确保 @identifier 的唯一性就好
     * @param identifier cell 标识符,通过 @dequeueReusableCell 获取重用 cell 时,会根据这个值匹配
     * @param maker 生成节点,当重用池里没有可用的节点时,会通过这个回调获取节点,需要在这个回调里面生成节点
     * @param poolComp 节点自定义组件,可以通过这个组件跟 @NodePool 的重用业务关联起来
     */
    register(identifier: string, maker: () => Node, poolComp?: (new (...args: any[]) => YXCollectionViewCell) | null): void;
    /**
     * 通过标识符从重用池里取出一个可用的 cell 节点
     * @param identifier 注册时候的标识符
     * @returns
     */
    dequeueReusableCell(identifier: string): Node;
    /**
     * 配置每块内容对应的 UI 节点
     * 在这个方法里,只需要关心 @indexPath 这个位置对应的节点应该是用注册过的哪个类型的 Node 节点,然后通过 @dequeueReusableCell 生成对应的 Node
     * 注意: 不要在这个方法里创建新的节点对象
     * @example
     * yourList.cellForItemAt = (indexPath, collectionView) => {
     *      return collectionView.dequeueReusableCell(`your identifier`)
     * }
     * @returns 注意: 这个方法返回的 cell,必须是通过 @dequeueReusableCell 匹配到的 Node
     */
    cellForItemAt: (indexPath: YXIndexPath, collectionView: YXCollectionView) => Node;
    /**
     * cell 添加到滚动视图上之后执行,在这个方法里更新 cell 显示的 UI 内容
     * 可以通过 @indexPath 区分 cell 的种类
     * 重要: 如果 cell 的大小不是固定的,需要在这里重新调整子节点的位置,避免布局错乱
     */
    onCellDisplay: (cell: Node, indexPath: YXIndexPath, collectionView: YXCollectionView) => void;
    /**
     * 点击到节点后调用
     */
    onTouchItemAt: (indexPath: YXIndexPath, collectionView: YXCollectionView) => void;
    /**
     * 布局属性
     */
    layout: YXLayout;
    /**
     * 获取当前正在显示的所有节点
     */
    visibleNodes: Node[];
    get visibleIndexPaths(): YXIndexPath[];
    /**
     * 获取当前正在显示的某个节点
     * @param indexPath
     */
    getVisibleNode(indexPath: YXIndexPath): Node | null;
    /**
     * 获取指定节点的索引
     * @param node
     * @returns
     */
    getVisibleNodeIndexPath(node: Node): YXIndexPath;
    /**
     * 刷新列表数据
     */
    reloadData(): void;
    /**
     * 刷新当前可见节点
     * @param force true: 立即刷新  false: 下帧刷新
     */
    markForUpdateVisibleData(force?: boolean): void;
    /**
     * 滚动到指定节点的位置
     * @returns
     */
    scrollTo(indexPath: YXIndexPath, timeInSecond?: number, attenuated?: boolean): void;
    /**
     * 生命周期方法
     */
    protected onLoad(): void;
    protected onDestroy(): void;
    protected update(dt: number): void;
}

YXLayoutAttributes

列表内的节点的布局属性,决定了节点最终在列表内该如何展示

/**
 * 节点的布局属性
 */
export declare class YXLayoutAttributes {
    /**
     * 节点索引
     */
    indexPath: YXIndexPath;
    /**
     * 节点在滚动视图中的位置和大小属性
     * origin 属性表示节点在父视图坐标系中的左上角的位置,size 属性表示节点的宽度和高度
     */
    frame: math.Rect;
    /**
     * 节点层级
     * 越小会越早的添加到滚动视图上
     * https://docs.cocos.com/creator/manual/zh/ui-system/components/editor/ui-transform.html?h=uitrans
     * 备注: 内部暂时是通过节点的 siblingIndex 实现的,如果自定义 layout 有修改这个值的需求,需要重写 layout 的 @shouldUpdateAttributesZIndex 方法,默认情况下会忽略这个配置
     */
    zIndex: number;
    /**
     * 节点变换 - 缩放
     */
    scale: math.Vec3;
    /**
     * 节点变换 - 平移
     */
    offset: math.Vec3;
    /**
     * 节点变换 - 旋转
     * 备注: 3D 变换似乎需要透视相机???
     */
    eulerAngles: math.Vec3;
    /**
     * 克隆当前布局属性
     */
    clone(): YXLayoutAttributes;
}

YXLayout

抽象基类,定义列表的布局方式
子类负责实现具体的布局算法,通过覆盖其中的方法来实现不同的布局效果。

/**
 * 布局规则
 * 这里只是约定出了一套接口,内部只是一些基础实现,具体布局方案通过子类重载去实现
 */
export declare abstract class YXLayout {
    constructor();
    /**
     * @required
     * 整个滚动区域大小
     * 需要在 @prepare 内初始化
     */
    contentSize: math.Size;
    /**
     * @required
     * 所有元素的布局属性
     * 需要在 @prepare 内初始化
     */
    attributes: YXLayoutAttributes[];
    /**
     * @required
     * 子类重写实现布局方案
     * 注意: 必须初始化滚动区域大小并赋值给 @contentSize 属性
     * 注意: 必须初始化所有的元素布局属性,并保存到 @attributes 数组
     */
    abstract prepare(collectionView: YXCollectionView): void;
    /**
     * @optional
     * 列表在首次更新数据后会执行这个方法
     * 在这个方法里设置滚动视图的初始偏移量
     */
    initOffset(collectionView: YXCollectionView): void;
    /**
     * @optional
     * 当一次手势拖动结束后会立即调用此方法
     * 实现这个方法的话滚动视图会自动滚动到此方法返回的位置
     * @param touchMoveVelocity 本次手势拖动速度
     * @param startOffset 本次手势拖动开始时滚动视图的偏移位置
     * @returns null 不处理
     */
    targetOffset(collectionView: YXCollectionView, touchMoveVelocity: math.Vec3, startOffset: math.Vec2): {
        offset: math.Vec2;
        time: number;
    };
    /**
     * @optional
     * 返回区域内可见的节点属性,并实时的调整这些节点变换效果
     * 根据实际的布局情况,计算出当前屏幕内需要显示的布局属性
     * 这个方法会直接影响到列表的性能,如果在自定义的时候对性能要求不高(比如明确知道数据量不多的情况下),可以忽略此方法
     * @param rect 当前滚动视图的可见区域
     */
    layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[];
    /**
     * @optional
     * 通过索引查找布局属性,默认 Array.find()
     * @param indexPath
     * @param collectionView
     */
    layoutAttributesForItemAtIndexPath(indexPath: YXIndexPath, collectionView: YXCollectionView): YXLayoutAttributes;
    /**
     * @optional
     * YXCollectionView 在调用 @scrollTo 方法时会触发这个方法,如果实现了这个方法,最终的滚动停止位置以这个方法返回的为准
     * @param indexPath
     * @returns 滚动视图偏移位置
     */
    scrollTo(indexPath: YXIndexPath, collectionView: YXCollectionView): math.Vec2;
    /**
     * @optional
     * @see YXLayoutAttributes.zIndex
     * @returns
     */
    shouldUpdateAttributesZIndex(): boolean;
}

YXFlowLayout

基本的排列样式
支持水平/垂直方向排列
当水平方向布局的时候,节点会按照由上至下,由左至右的方式排列。
当垂直方向布局的时候,节点会按照由左至右,由上至下的方式排列。
节点大小可以随意设置,排列不下的话会自动换行/列。

/**
 * 支持水平/垂直方向排列滚动
 */
export declare class YXFlowLayout extends YXLayout {
    /**
     * 滚动方向,默认垂直方向滚动
     */
    scrollDirection: YXFlowLayout.ScrollDirection;
    /**
     * 是否开启分页滚动效果
     */
    pagingEnabled: boolean;
    /**
     * @bug 如果节点大小差距很大,可能会导致计算屏幕内节点时不准确,出现节点不被正确添加到滚动视图上的问题 (使用瀑布流布局时问题明显)
     * @fix 可以通过此属性,追加屏幕显示的节点数量
     * 设置这个值会在检查是否可见的节点时,尝试检查更多的可能处于屏幕外的节点,具体设置多少要根据实际情况调试,一般如果都是正常大小的节点,不需要考虑这个配置
     * 设置负值会检查所有的节点
     */
    extraVisibleCount: number;
    /**
     * 元素大小
     */
    itemSize: math.Size | ((indexPath: YXIndexPath, layout: YXFlowLayout, collectionView: YXCollectionView) => math.Size);
    getItemSize(): math.Size;
    /**
     * 元素之间垂直间距
     */
    verticalSpacing: number | ((section: number, layout: YXFlowLayout, collectionView: YXCollectionView) => number);
    getVerticalSpacing(): number;
    /**
     * 元素之间水平间距
     */
    horizontalSpacing: number | ((section: number, layout: YXFlowLayout, collectionView: YXCollectionView) => number);
    getHorizontalSpacing(): number;
    /**
     * 边距
     */
    sectionInset: YXEdgeInsets | ((section: number, layout: YXFlowLayout, collectionView: YXCollectionView) => YXEdgeInsets);
    getSectionInset(): YXEdgeInsets;
    prepare(collectionView: YXCollectionView): void;
    initOffset(collectionView: YXCollectionView): void;
    targetOffset(collectionView: YXCollectionView, touchMoveVelocity: math.Vec3, startOffset: math.Vec2): {
        offset: math.Vec2;
        time: number;
    };
    layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[];
    layoutAttributesForItemAtIndexPath(indexPath: YXIndexPath, collectionView: YXCollectionView): YXLayoutAttributes;
    private _horizontal;
    private _vertical;
}
export declare namespace YXFlowLayout {
    /**
     * 滚动方向
     */
    enum ScrollDirection {
        /**
         * 水平滚动
         */
        HORIZONTAL = 0,
        /**
         * 垂直滚动
         */
        VERTICAL = 1
    }
}

YXMasonryFlowLayout

瀑布流排列样式
支持水平/垂直方向排列
当水平方向布局的时候,只能设置节点的宽度,高度固定为容器高度 / 内容行数,节点会自动排列到最短的一行。
当垂直方向布局的时候,只能设置节点的高度,宽度固定为容器宽度 / 内容列数,节点会自动排列到最短的一列。

/**
 * 瀑布流布局方案
 */
export declare class YXMasonryFlowLayout extends YXFlowLayout {
    /**
     * 分几行(水平滚动模式下)或者几列(垂直滚动模式下)展示
     */
    divide: number | ((section: number, layout: YXMasonryFlowLayout, collectionView: YXCollectionView) => number);
    /**
     * @see YXFlowLayout.extraVisibleCount
     */
    extraVisibleCount: number;
    /**
     * 水平滚动模式下,仅宽度生效
     * 垂直滚动模式下,仅高度生效
     */
    itemSize: math.Size | ((indexPath: YXIndexPath, layout: YXFlowLayout, collectionView: YXCollectionView) => math.Size);
    prepare(collectionView: YXCollectionView): void;
    private _masonry_horizontal;
    private _masonry_vertical;
}

YXCoverLayout

突出选中节点布局样式
支持水平/垂直方向排列
固定一行(水平)或一列(垂直)排列节点,非选中节点会被缩小

/**
 * 用来实现突出选中节点效果的布局规则
 */
export declare class YXCoverLayout extends YXFlowLayout {
    mode: YXCoverLayout.Mode;
    /**
     * 禁止外部使用的父类属性
     */
    sectionInset: never;
    getSectionInset(): never;
    /**
     * 元素大小
     */
    itemSize: math.Size;
    getItemSize(): math.Size;
    /**
     * 非选中节点的缩放系数
     */
    scaleValue: number;
    /**
     * 构造函数,此类布局必须要确定节点大小属性
     * @param itemSize
     */
    constructor(itemSize: math.Size);
    prepare(collectionView: YXCollectionView): void;
    targetOffset(collectionView: YXCollectionView, touchMoveVelocity: math.Vec3, startOffset: math.Vec2): {
        offset: math.Vec2;
        time: number;
    };
    scrollTo(indexPath: YXIndexPath, collectionView: YXCollectionView): math.Vec2;
    layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[];
    shouldUpdateAttributesZIndex(): boolean;
}
export declare namespace YXCoverLayout {
    enum Mode {
        /**
         * 缩放非选中的节点
         */
        DEFAULT = 0
    }
}

sixsixsix

v1.0.2

YXCarouselLayout

旋转木马布局样式,仅支持了水平滚动方向
会直接加载所有节点,适合少量数据

/**
 * 旋转木马,会加载所有节点,适合少量数据
 */
export declare class YXCarouselLayout extends YXLayout {
    /**
     * 节点大小
     */
    itemSize: math.Size;
    /**
     * 是否开启循环滚动
     */
    loop: boolean;
    /**
     * 半径
     */
    radius: number;
    /**
     * 最远节点的缩放比例,取值范围 [ 0 ~ 1 ]
     * 模拟近大远小的视觉效果
     */
    minScale: number;
    /**
     * 最远节点的透明度变化,取值范围 [ 0 ~ 1 ]
     */
    minAlpha: number;
    /**
     * 整体绕 x 轴旋转角度
     * 备注: 只是影响节点的 y 坐标位置,并不会有 3d 旋转效果
     */
    angleX: number;
}

wx_xuanzhuanmuma


YXCoverLayout

新增了旋转角度配置,可以配合 3d 相机实现一些 3d 旋转效果,更新了 3d 节点演示项目 (3D画廊)

/**
 * 用来实现突出选中节点效果的布局规则
 */
export declare class YXCoverLayout extends YXFlowLayout {
    /**
     * 禁止外部使用的父类属性
     */
    sectionInset: never;
    getSectionInset(): never;
    /**
     * 节点大小
     */
    itemSize: math.Size;
    getItemSize(): math.Size;
    /**
     * 非选中节点的缩放系数
     */
    scaleValue: number;
    /**
     * 非选中节点的 x 轴旋转角度
     * 仅支持 3D 节点
     */
    angleX: number;
    /**
     * 非选中节点的 y 轴旋转角度
     * 仅支持 3D 节点
     */
    angleY: number;
    /**
     * 非选中节点的 z 轴旋转角度
     */
    angleZ: number;
    /**
     * 构造函数,此类布局必须要确定节点大小属性
     * @param itemSize
     */
    constructor(itemSize: math.Size);
}

wx_hualang


关于 3d cell 节点

  • 重要: 有关 3d 变换效果的是因个人兴趣尝试实现,未实际在项目中使用过
  • 暂时只调试了 Creator 3.8.0 版本
  • 列表仍为 2d 节点不做变化,只是把 cell 节点改为 3d 相机照得到的节点 (后面统称 3d节点)
  • 需要在场景内自己管理一个 3d 相机用来照 3d 节点
  • 保证 3d 节点的 layer 设置正确可以被 3d 相机照到
  • 列表的 mask 属性要设置为 false (备注: 3d 节点的父节点添加 mask 组件,会导致看不到子节点 ???)
  • 列表的 is3DCell 属性要设置为 true,这个设置是为了避免节点点击事件错乱
  • 调整 3d 相机参数,比如远近(z) 和 相机视角大小(fov),需要实际的调试出一个感觉比较合适的值
  • 当列表 cell 为 3d 节点时,列表仅做展示,节点的点击事件需要通过 射线检测 自行实现

1赞

这个库压缩后有多少kb代码?

整个项目的大小是 744kb,组件相关的文件是 68kb (源文件)
image

买了后用你的代码库,不包含你的demo,就是引入你的这个虚拟列表库是68KB是吧

是的,实际上,lib 目录下的文件也并不是必须要全部引入的
yx-collection-view.ts 作为核心是必须要引入
其他可以按照自己的布局需求来引入,比如说如果 flow-layout 可以满足所有布局需求的话,可以只引入 yx-collection-view.tsyx-flow-layout.ts 两个文件就好
又比如需要用到瀑布流布局的话,因为 yx-masonry-flow-layout.ts 是继承 yx-flow-layout.ts 的,所以一共需要引入 yx-collection-view.ts , yx-flow-layout.tsyx-masonry-flow-layout.ts 三个文件
其他同理,查看布局需求,查看继承关系,然后选择引入文件.

买!买 ! 买!

已经买了, 功能还是很全很强大, 但是有几点使用建议:
YXFlowLayout的设置,感觉做成编辑器属性是否更好,
还有组件的cell 是否可以弄成编辑器里面的数组,cell直接挂在此列表组件上,不需要写代码去register
不然感觉每次组件初始化要写好大一堆代码, 组件的易用性大大降低了。

首先感谢购买!!

然后是支持编辑器配置的问题,为了适应不同的布局规则,列表的 layout 声明是个抽象 YXLayout 类型,具体的布局实现 (比如间距,节点大小之类的) 是 YXLayout 的子类决定的,在编辑器阶段,无法知道列表要用到哪个布局规则,如果要在编辑器阶段支持选择布局规则的话,又需要在编辑器针对每个布局规则实现不同的特性配置,维护起来会不方便。另外一些可能不统一的设置比如节点大小,如果需求是列表内节点大小不一致,最终还是需要通过代码根据实际数据动态调整

通过编辑器注册 cell 节点类型应该可以实现,下个版本会补充一下 :grinning:

另外对于单一 cell 类型的列表来说,使用起来确实有点繁琐了 :joy:,后续我看看针对单一 cell 类型的情况做一下优化,简化一些操作

demo2,水平滚动,分页
当切换分页时,我需要获取到切换后的那个分页的indexPath,然后显示相对的数据,有地方可以监听吗?

论坛帖子更新起来不是很方便,新建了一个简易的说明文档,点击前往

另外最新版本新增了可选的节点加载模式/回收模式,刚刚加的功能,目前测试下来表现正常,应该可以解决大多数实际使用中的抖动问题
这个版本会骨折优惠 3 天,到周末截止,有兴趣的可以支持一下,碰到的大问题小问题或者建议都可以反馈一下

挺不错 买了

:smiling_face_with_three_hearts:

买了 支持了

请问支持滑动条吗,想在windows上用

:smiling_face_with_three_hearts:

是基于 ScrollView 实现的,滑动条的话就是用 cc 的 ScrollBar 组件,就是滑轮操作目前是禁掉了,可以先加我 qq 看看

9.9很值