开贴补充 虚拟列表 商店描述,介绍一下组件接口
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
}
}
- 参考 UICollectionView 实现
- 商店地址