mirror of
https://github.com/568071718/creator-collection-view
synced 2025-12-10 22:58:50 +00:00
添加一些演示场景
This commit is contained in:
144
list-3x/assets/lib/page-layout.ts
Normal file
144
list-3x/assets/lib/page-layout.ts
Normal file
@@ -0,0 +1,144 @@
|
||||
import { log, math, warn } from "cc";
|
||||
import { YXCollectionView, YXIndexPath, YXLayout, YXLayoutAttributes } from "./yx-collection-view";
|
||||
|
||||
/**
|
||||
* PageView 布局
|
||||
*/
|
||||
export class PageLayout extends YXLayout {
|
||||
/**
|
||||
* 是否开启分页效果
|
||||
*/
|
||||
private pagingEnabled: boolean = true
|
||||
|
||||
/**
|
||||
* 分页效果开启时,自动吸附动画时间
|
||||
*/
|
||||
pagingAnimationDuration: number = 0.5
|
||||
|
||||
/**
|
||||
* 循环滚动,默认关闭
|
||||
* 注意: 当开启循环滚动时,YXCollectionView 需要额外设置 `ignoreScrollEndedDuringAutoScroll = true`
|
||||
* 注意: 开启循环滚动会生成较大范围的 `indexPath`,在使用索引的时候需要进行取余处理
|
||||
*
|
||||
* @example
|
||||
* listComp.ignoreScrollEndedDuringAutoScroll = true
|
||||
* listComp.numberOfItems = () => {
|
||||
* return <data-length>
|
||||
* }
|
||||
* listComp.cellForItemAt = (indexPath, collectionView) => {
|
||||
* let index = indexPath.row % <data-length> // 通过取余获取真实数据索引
|
||||
* const cell = collectionView.dequeueReusableCell(`cell`)
|
||||
* return cell
|
||||
* }
|
||||
*/
|
||||
loop: boolean = false
|
||||
|
||||
/**
|
||||
* 仅开启循环滚动时生效,由于循环滚动是伪循环,如果不间断的朝着某一个方向一直滑是会滑到头的 (就像苹果的闹钟时间可以滑到尽头...)
|
||||
* 调整这个属性可以放大滚动范围,避免滑动到头穿帮
|
||||
* 会生成额外的布局属性,建议范围 1 ~ 10,默认: 5 (实际情况可以看数据压力,数据不多的话可以设置更大)
|
||||
*/
|
||||
scrollRangeMultiplier: number = 5
|
||||
private get safeScrollRangeMultiplier(): number {
|
||||
let value = Math.floor(this.scrollRangeMultiplier)
|
||||
return Math.max(1, value)
|
||||
}
|
||||
|
||||
prepare(collectionView: YXCollectionView): void {
|
||||
collectionView.scrollView.horizontal = true
|
||||
collectionView.scrollView.vertical = false
|
||||
if (collectionView.scrollDirection === YXCollectionView.ScrollDirection.VERTICAL) {
|
||||
warn(`PageLayout 仅支持水平方向排列`)
|
||||
}
|
||||
|
||||
const numberOfSections = collectionView.getNumberOfSections()
|
||||
if (numberOfSections > 1) { warn(`GridLayout 暂时不支持分区模式`) }
|
||||
|
||||
let contentSize = collectionView.scrollView.view.contentSize.clone()
|
||||
let attrs = []
|
||||
|
||||
let itemSize = collectionView.scrollView.view.contentSize
|
||||
let numberOfItems = collectionView.getNumberOfItems(0)
|
||||
if (this.loop) {
|
||||
numberOfItems = numberOfItems * 3 * this.safeScrollRangeMultiplier
|
||||
if (collectionView.ignoreScrollEndedDuringAutoScroll == false) {
|
||||
warn(`PageLayout: 开启循环滚动时建议将 YXCollectionView.ignoreScrollEndedDuringAutoScroll 设置为 true`)
|
||||
}
|
||||
}
|
||||
for (let index = 0; index < numberOfItems; index++) {
|
||||
let attr = YXLayoutAttributes.layoutAttributesForCell(new YXIndexPath(0, index))
|
||||
attr.frame.x = itemSize.width * index
|
||||
attr.frame.y = 0
|
||||
attr.frame.width = itemSize.width
|
||||
attr.frame.height = itemSize.height
|
||||
attrs.push(attr)
|
||||
contentSize.width = Math.max(contentSize.width, attr.frame.xMax)
|
||||
}
|
||||
|
||||
this.attributes = attrs
|
||||
this.contentSize = contentSize
|
||||
}
|
||||
|
||||
initOffset(collectionView: YXCollectionView): void {
|
||||
if (this.loop) {
|
||||
let numberOfItems = collectionView.getNumberOfItems(0)
|
||||
let offset = new math.Vec2()
|
||||
offset.x = numberOfItems * this.safeScrollRangeMultiplier * collectionView.scrollView.view.width
|
||||
offset.y = 0
|
||||
collectionView.scrollView.scrollToOffset(offset, 0)
|
||||
} else {
|
||||
collectionView.scrollView.scrollToLeft()
|
||||
}
|
||||
}
|
||||
|
||||
targetOffset(collectionView: YXCollectionView, touchMoveVelocity: math.Vec3, startOffset: math.Vec2, originTargetOffset: math.Vec2, originScrollDuration: number): { offset: math.Vec2; time?: number; attenuated?: boolean; } | null {
|
||||
if (this.pagingEnabled == false) {
|
||||
return null
|
||||
}
|
||||
let offset = collectionView.scrollView.getScrollOffset()
|
||||
offset.x = - offset.x
|
||||
let threshold = 0.2
|
||||
let idx = Math.round(offset.x / collectionView.scrollView.view.width)
|
||||
let r = touchMoveVelocity.x / collectionView.scrollView.view.width
|
||||
if (startOffset && Math.abs(r) >= threshold) {
|
||||
idx = Math.round(startOffset.x / collectionView.scrollView.view.width) + (r > 0 ? -1 : 1)
|
||||
}
|
||||
offset.x = idx * collectionView.scrollView.view.width
|
||||
return { offset: offset, time: this.pagingAnimationDuration }
|
||||
}
|
||||
|
||||
layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[] {
|
||||
if (collectionView.scrollView.view.width <= 0 || this.attributes.length <= 0) {
|
||||
return super.layoutAttributesForElementsInRect(rect, collectionView)
|
||||
}
|
||||
// 直接计算出当前元素位置,另外额外返回左右两边的元素
|
||||
let result = []
|
||||
let idx = Math.round(rect.x / collectionView.scrollView.view.width)
|
||||
let previousIdx = idx - 1
|
||||
let latterIdx = idx + 1
|
||||
if (idx >= 0 && idx < this.attributes.length) {
|
||||
result.push(this.attributes[idx])
|
||||
}
|
||||
if (previousIdx >= 0 && previousIdx < this.attributes.length && previousIdx != idx) {
|
||||
result.push(this.attributes[previousIdx])
|
||||
}
|
||||
if (latterIdx >= 0 && latterIdx < this.attributes.length && latterIdx != idx) {
|
||||
result.push(this.attributes[latterIdx])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
onScrollEnded(collectionView: YXCollectionView): void {
|
||||
if (this.loop == false) {
|
||||
return
|
||||
}
|
||||
let numberOfItems = collectionView.getNumberOfItems(0)
|
||||
let offset = collectionView.scrollView.getScrollOffset()
|
||||
offset.x = - offset.x
|
||||
let idx = Math.round(offset.x / collectionView.scrollView.view.width) % numberOfItems
|
||||
offset.x = collectionView.scrollView.view.width * (numberOfItems * this.safeScrollRangeMultiplier + idx)
|
||||
collectionView.scrollView.scrollToOffset(offset)
|
||||
// 直接设置滚动位置不会触发刷新,这里强制刷新一下
|
||||
collectionView.markForUpdateVisibleData(true)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user