SuperScrollView_3.X/assets/core/super-layout.ts
2022-01-13 17:21:54 +08:00

1437 lines
60 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* @Author: steveJobs
* @Email: icipiqkm@gmail.com
* @Date: 2021-8-1 01:15:04
* @Last Modified by: steveJobs
* @Last Modified time: 2021-8-1 14:35:43
* @Description:
*/
import { _decorator, Component, Node, ccenum, UITransform, SystemEventType, director, Vec3, EventHandler, instantiate, Prefab, Size, Vec2, size, ScrollView, PageView, PageViewIndicator } from 'cc';
import { SuperScrollview } from './super-scrollview';
const { ccclass, property, requireComponent } = _decorator;
const EPSILON = 1e-5
enum Type {
HORIZONTAL = 0,
VERTICAL = 1,
}
ccenum(Type)
enum VerticalAxisDirection {
TOP_TO_BOTTOM = 0,
BOTTOM_TO_TOP = 1
}
ccenum(VerticalAxisDirection)
enum HorizontalAxisDirection {
LEFT_TO_RIGHT = 0,
RIGHT_TO_LEFT = 1
}
ccenum(HorizontalAxisDirection)
enum ScrollDirection {
NONE = 0,
HEADER = 1,
FOOTER = 2,
}
enum IndexVerticalAxisDirection {
TOP = 0,
BOTTOM = 1,
}
ccenum(IndexVerticalAxisDirection)
enum IndexHorizontalAxisDirection {
LEFT = 0,
RIGHT = 1
}
ccenum(IndexHorizontalAxisDirection)
@ccclass('SuperLayout')
@requireComponent(UITransform)
export class SuperLayout extends Component {
static VerticalAxisDirection = VerticalAxisDirection
static HorizontalAxisDirection = HorizontalAxisDirection
@property(SuperScrollview) scrollView!: SuperScrollview
@property(UITransform) view!: UITransform
@property(Prefab) prefab!: Prefab
@property({ type: Type }) layoutType: Type = Type.VERTICAL
@property({
type: IndexVerticalAxisDirection,
visible: function () { return (this as any).layoutType == Type.VERTICAL && !(this as any).autoCenter }
}) indexVerticalAxisDirection = IndexVerticalAxisDirection.TOP
@property({
type: IndexHorizontalAxisDirection,
visible: function () { return (this as any).layoutType == Type.HORIZONTAL && !(this as any).autoCenter }
}) indexHorizontalAxisDirection = IndexHorizontalAxisDirection.LEFT
@property({ type: VerticalAxisDirection }) verticalAxisDirection = VerticalAxisDirection.TOP_TO_BOTTOM
@property({ type: HorizontalAxisDirection }) horizontalAxisDirection = HorizontalAxisDirection.LEFT_TO_RIGHT
@property({ tooltip: "最小值=1大于1就是Grid模式" }) groupItemTotal: number = 1
@property({ tooltip: "决定最多创建Prefab的数量" }) multiple: number = 2
@property({ tooltip: "顶部填充" }) paddingTop: number = 0
@property({ tooltip: "底部填充" }) paddingBottom: number = 0
@property({ tooltip: "左侧填充" }) paddingLeft: number = 0
@property({ tooltip: "右侧填充" }) paddingRight: number = 0
@property({ tooltip: "横轴间距" }) spacingX: number = 0
@property({ tooltip: "纵轴间距" }) spacingY: number = 0
@property({ tooltip: "计算缩放后的尺寸" }) affectedByScale: boolean = false
@property({ tooltip: "开启翻页模式" }) isPageView: boolean = false
@property({
tooltip: "每个页面翻页时所需时间。单位:秒",
visible: function () { return (this as any).isPageView }
}) pageTurningSpeed = 0.3
@property({
type: PageViewIndicator,
visible: function () { return (this as any).isPageView }
}) indicator!: PageViewIndicator
@property({
slide: true,
range: [0, 1, 0.01],
tooltip: "滚动临界值,默认单位百分比,当拖拽超出该数值时,松开会自动滚动下一页,小于时则还原",
visible: function () { return (this as any).isPageView }
}) scrollThreshold = 0.5
@property({
tooltip: "快速滑动翻页临界值。当用户快速滑动时,会根据滑动开始和结束的距离与时间计算出一个速度值,该值与此临界值相比较,如果大于临界值,则进行自动翻页",
visible: function () { return (this as any).isPageView }
}) autoPageTurningThreshold = 100
@property({
type: EventHandler,
visible: function () { return (this as any).isPageView }
}) pageEvents: EventHandler[] = []
@property({
tooltip: "开启自动居中",
visible: function () { return !(this as any).isPageView }
}) autoCenter: boolean = false
@property({
tooltip: "自动居中的滚动时间",
visible: function () { return (this as any).autoCenter }
}) centerTime: number = 1
@property({
type: Node,
tooltip: "自动居中的参考节点如果为空、则默认选择View中心",
visible: function () { return (this as any).autoCenter }
}) centerNode!: Node
@property({
type: Vec2,
tooltip: "自动居中时、Item的居中锚点",
visible: function () { return (this as any).autoCenter }
}) centerAnchor: Vec2 = new Vec2(.5, .5)
@property({ tooltip: "上/左 无限循环" }) headerLoop: boolean = false
@property({ tooltip: "下/右 无限循环" }) footerLoop: boolean = false
@property(EventHandler) refreshItemEvents: EventHandler[] = []
private stretchLock: {
index?: number,
timeInSecond?: number,
boundary?: Vec3,
reverse?: boolean,
} = {}
private _currPageIndex: number = 0
get currPageIndex() {
return this._currPageIndex
}
private _lastPageIndex: number = 0
get lastPageIndex() {
return this._lastPageIndex
}
private isRestart: boolean = false
/** 当前滚动方向 */
private scrollDirection: ScrollDirection = ScrollDirection.NONE
/** 是否垂直滚动 */
get vertical(): boolean { return this.layoutType == Type.VERTICAL }
/** 是否水平滚动 */
get horizontal(): boolean { return this.layoutType == Type.HORIZONTAL }
get transform(): UITransform | null { return this.node._uiProps.uiTransformComp }
/** View 可容纳的宽度 */
get accommodWidth() {
return this.view.width - this.paddingLeft - this.paddingRight
}
/** View 可容纳的高度 */
get accommodHeight() {
return this.view.height - this.paddingTop - this.paddingBottom
}
/** 头部的节点 */
get header(): UITransform | null {
if (this.node.children.length == 0) return null
return this.node.children[0]._uiProps.uiTransformComp
}
/** 底部的节点 */
get footer(): UITransform | null {
if (this.node.children.length == 0) return null
return this.node.children[this.node.children.length - 1]._uiProps.uiTransformComp
}
/** 头部索引 */
get headerIndex(): number {
if (!this.header) return -1
let node: any = this.header.node
return node["__index"]
}
/** 底部索引 */
get footerIndex(): number {
if (!this.footer) return -1
let node: any = this.footer.node
return node["__index"]
}
/** Item起始位置 */
get viewStartPoint(): Vec3 {
let pos = new Vec3()
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
pos.x = this.view.width * -0.5 + this.paddingLeft
} else {
pos.x = this.view.width * 0.5 - this.paddingRight
}
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
pos.y = this.view.height * 0.5 - this.paddingTop
} else {
pos.y = this.view.height * -0.5 + this.paddingBottom
}
return pos
}
/** View 头部边界 */
get viewHeaderBoundary(): number {
return this.vertical ? this.view.height * 0.5 : this.view.width * -0.5
}
/** View 底部边界 */
get viewFooterBoundary(): number {
return this.vertical ? this.view.height * -0.5 : this.view.width * 0.5
}
/** 头部节点边界 */
get headerBoundary(): number {
if (!this.header) return 0
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
return this.node.position.y + this.getItemYMax(this.header) + this.paddingTop
} else {
return this.node.position.y + this.getItemYMin(this.header) - this.paddingBottom
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
return this.node.position.x + this.getItemXMin(this.header) - this.paddingLeft
} else {
return this.node.position.x + this.getItemXMax(this.header) + this.paddingRight
}
}
}
/** 底部节点边界 */
get footerBoundary(): number {
if (!this.footer) return 0
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
return this.node.position.y + this.getItemYMin(this.footer) - this.paddingBottom
} else {
return this.node.position.y + this.getItemYMax(this.footer) + this.paddingTop
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
return this.node.position.x + this.getItemXMax(this.footer) + this.paddingRight
} else {
return this.node.position.x + this.getItemXMin(this.footer) - this.paddingLeft
}
}
}
/** 自动居中节点头部边界 */
get centerHeaderBoundary() {
let key = this.vertical ? "y" : "x"
var offset
if (this.centerNode) {
offset = this.viewHeaderBoundary - (this.centerNode.position as any)[key]
} else {
offset = this.viewHeaderBoundary - (this.view.node.position as any)[key]
}
if (this.vertical && this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM || this.horizontal && this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
return this.headerBoundary + offset
} else {
return this.footerBoundary + offset
}
}
/** 自动居中节点底部边界 */
get centerFooterBoundary() {
let key = this.vertical ? "y" : "x"
var offset
if (this.centerNode) {
offset = this.viewFooterBoundary - (this.centerNode.position as any)[key]
} else {
offset = this.viewFooterBoundary - (this.view.node.position as any)[key]
}
if (this.vertical && this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM || this.horizontal && this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
return this.footerBoundary + offset
} else {
return this.headerBoundary + offset
}
}
/** 是否超出左侧边界 */
get isOfLeftBoundary(): number {
if (this.vertical) return 0
if (this.autoCenter) {
if (this.scrollDirection == ScrollDirection.HEADER) {
return this.centerHeaderBoundary
}
return 0
}
if (this.headerLoop) {
if (this.header) return 0
return this.viewHeaderBoundary + this.node.position.x
}
if (!this.header || this.fixedItemWidth <= this.view.width) {
return this.viewHeaderBoundary + this.node.position.x
}
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (this.headerIndex == 0) {
return this.headerBoundary
}
} else {
if (this.footerIndex == this.itemTotal - 1) {
return this.footerBoundary
}
}
return 0
}
/** 是否超出顶部边界 */
get isOfTopBoundary(): number {
if (!this.vertical) return 0
if (this.autoCenter) {
if (this.scrollDirection == ScrollDirection.HEADER) {
return this.centerHeaderBoundary
}
return 0
}
if (this.headerLoop) {
if (this.header) return 0
return this.viewHeaderBoundary + this.node.position.y
}
if (!this.header || this.fixedItemHeight <= this.view.height) {
return this.viewHeaderBoundary + this.node.position.y
}
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (this.headerIndex == 0) {
return this.headerBoundary
}
} else {
if (this.footerIndex == this.itemTotal - 1) {
return this.footerBoundary
}
}
return 0
}
/** 是否超出右侧边界 */
get isOfRightBoundary(): number {
if (this.vertical) return 0
if (this.autoCenter) {
if (this.scrollDirection == ScrollDirection.FOOTER) {
return this.centerFooterBoundary
}
return 0
}
if (this.footerLoop) {
if (this.footer) return 0
return this.viewFooterBoundary + this.node.position.x
}
if (!this.footer || this.fixedItemWidth <= this.view.width) {
return this.viewFooterBoundary + this.node.position.x
}
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (this.footerIndex == this.itemTotal - 1) {
return this.footerBoundary
}
} else {
if (this.headerIndex == 0) {
return this.headerBoundary
}
}
return 0
}
/** 是否超出底部边界 */
get isOfButtomBoundary(): number {
if (!this.vertical) return 0
if (this.autoCenter) {
if (this.scrollDirection == ScrollDirection.FOOTER) {
return this.centerFooterBoundary
}
return 0
}
if (this.footerLoop) {
if (this.footer) return 0
return this.viewFooterBoundary + this.node.position.y
}
if (!this.footer || this.fixedItemHeight <= this.view.height) {
return this.viewFooterBoundary + this.node.position.y
}
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (this.footerIndex == this.itemTotal - 1) {
return this.footerBoundary
}
} else {
if (this.headerIndex == 0) {
return this.headerBoundary
}
}
return 0
}
/** 从头部到底部的所有Item高度总和 */
get fixedItemHeight(): number {
if (!this.header) return 0
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
return Math.abs(this.getItemYMax(this.header)) + Math.abs(this.getItemYMin(this.footer))
} else {
return Math.abs(this.getItemYMin(this.header)) + Math.abs(this.getItemYMax(this.footer))
}
}
/** 从头部到底部的所有Item宽度总和 */
get fixedItemWidth(): number {
if (!this.header) return 0
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
return Math.abs(this.getItemXMin(this.header)) + Math.abs(this.getItemXMax(this.footer))
} else {
return Math.abs(this.getItemXMax(this.header)) + Math.abs(this.getItemXMin(this.footer))
}
}
/** 返回 header到 footer 之间的整体尺寸 如果Item数量不足以撑开View 则返回View尺寸 最小值是View尺寸 */
get contentSize(): Size {
if (this.node.children.length == 0) return this.view.contentSize
let size = new Size(this.view.contentSize.width, this.view.contentSize.height)
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
size.height = this.headerBoundary + -this.footerBoundary
} else {
size.height = this.footerBoundary + -this.headerBoundary
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
size.width = this.footerBoundary + -this.headerBoundary
} else {
size.width = this.headerBoundary + -this.footerBoundary
}
}
if (size.width < this.view.contentSize.width) {
size.width = this.view.contentSize.width
}
if (size.height < this.view.contentSize.height) {
size.height = this.view.contentSize.height
}
return size
}
private prevPos: Vec3 = new Vec3(0, 0, 0)
private _maxPrefabTotal: number = 0
/** 已被创建的Item数量 */
get maxPrefabTotal(): number { return this._maxPrefabTotal }
private currentCreateItemTotal: number = 0
private _itemTotal: number = 0
/** 数据长度 */
get itemTotal(): number { return this._itemTotal }
private _centerPosition!: Vec3
/** 自动居中的参考位置 */
get centerPosition(): Vec3 {
if (!this._centerPosition) {
this._centerPosition = new Vec3()
if (this.autoCenter) {
if (this.centerNode) {
let worldPos = this.centerNode.parent?._uiProps.uiTransformComp?.convertToWorldSpaceAR(this.centerNode.position)!
this._centerPosition = this.view.convertToNodeSpaceAR(worldPos)
}
} else {
if (this.vertical) {
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.TOP) {
this._centerPosition.y = this.viewHeaderBoundary
} else {
this._centerPosition.y = this.viewFooterBoundary
}
} else {
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.LEFT) {
this._centerPosition.x = this.viewHeaderBoundary
} else {
this._centerPosition.x = this.viewFooterBoundary
}
}
}
}
return this._centerPosition
}
onLoad() {
this.transform?.setAnchorPoint(new Vec2(.5, .5))
this.transform?.setContentSize(this.view.contentSize)
this.node.setPosition(Vec3.ZERO)
if (this.isPageView) this.autoCenter = false
this.scrollView.view?.node.on(Node.EventType.SIZE_CHANGED, this.onViewSizeChange, this)
Object.defineProperty(this.transform, "contentSize", { get: () => this.contentSize })
Object.defineProperty(this.transform, "width", { get: () => this.contentSize.width })
Object.defineProperty(this.transform, "height", { get: () => this.contentSize.height })
}
onEnable() {
this.addEventListener()
}
onDisable() {
this.removeEventListener()
}
/**
* 更新item数量
* @param count
* @param onRefreshLastItem 如果你确定只需要刷新最后一个item 那么这个设置成true 就不会刷新所有数据
*/
total(count: number, refreshLastItem: boolean = false): this {
this.currentCreateItemTotal = count
this.scrollDirection = ScrollDirection.HEADER
this.createItems(count, refreshLastItem)
let offset = count - this.itemTotal
this._itemTotal = count
this.refreshItems(offset, refreshLastItem)
if (!refreshLastItem) this.updateItems()
this.scrollView.startAutoScroll()
this.scrollView.release()
if (this.indicator) {
this.indicator.setPageView((this.scrollView as any));
}
if (this.autoCenter) {
this.scrollToCenter()
}
return this
}
/**
* 刷新所有item
*/
updateItems(): this {
this.resetIndexStartToEnd(this.headerIndex)
return this
}
/** 告知组件你的节点尺寸 */
updateItemSize(node: Node, size: Size) {
if (this.groupItemTotal > 1) return
if (!node || !size) return
(node as any)["__runtime_size"] = size
this.onChangeChildSize(node._uiProps.uiTransformComp!)
}
/** 自动居中到最近Item */
scrollToCenter() {
this.soonFinish()
}
/** 滚动到头部 */
scrollToHeader(timeInSecond?: number) {
var headerOrFooter = 0
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
headerOrFooter = this.viewHeaderBoundary
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.BOTTOM) {
headerOrFooter -= this.header?.height! + this.paddingTop + this.paddingBottom
}
} else {
headerOrFooter = this.viewFooterBoundary
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.TOP) {
headerOrFooter += this.header?.height! + this.paddingTop + this.paddingBottom
}
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
headerOrFooter = this.viewHeaderBoundary
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.RIGHT) {
headerOrFooter += this.header?.width! + this.paddingLeft + this.paddingRight
}
} else {
headerOrFooter = this.viewFooterBoundary
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.LEFT) {
headerOrFooter -= this.header?.width! + this.paddingLeft + this.paddingRight
}
}
}
this.scrollToIndex(0, timeInSecond, new Vec3(headerOrFooter, headerOrFooter))
}
/** 滚动到尾部 */
scrollToFooter(timeInSecond?: number) {
var headerOrFooter = 0
if (this.vertical) {
if (this.fixedItemHeight < this.view.height) return
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
headerOrFooter = this.viewFooterBoundary
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.BOTTOM) {
headerOrFooter += this.footer?.height! + this.paddingTop + this.paddingBottom
}
} else {
headerOrFooter = this.viewHeaderBoundary
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.TOP) {
headerOrFooter -= this.footer?.height! + this.paddingTop + this.paddingBottom
}
}
} else {
if (this.fixedItemWidth < this.view.width) return
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
headerOrFooter = this.viewFooterBoundary
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.RIGHT) {
headerOrFooter -= this.footer?.width! + this.paddingLeft + this.paddingRight
}
} else {
headerOrFooter = this.viewHeaderBoundary
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.LEFT) {
headerOrFooter += this.footer?.width! + this.paddingLeft + this.paddingRight
}
}
}
this.scrollToIndex(this.itemTotal - 1, timeInSecond, new Vec3(headerOrFooter, headerOrFooter), true)
}
private isNearFooter(index: number) {
let nearFooter = false
let flag = index > this.footerIndex && index < this.headerIndex
if (flag) {
let result = Math.abs(index - this.headerIndex) < Math.abs(index - this.footerIndex)
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
nearFooter = !result
} else {
nearFooter = result
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
nearFooter = !result
} else {
nearFooter = result
}
}
} else if (index > this.footerIndex) {
if (this.vertical) {
nearFooter = this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM ? true : false
} else {
nearFooter = this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT ? true : false
}
} else if (index < this.headerIndex) {
if (this.vertical) {
nearFooter = this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM ? false : true
} else {
nearFooter = this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT ? false : true
}
}
return nearFooter
}
private getFooterOffset(index: number) {
let footerOffset = this.footerIndex % this.groupItemTotal
let indexOffset = index % this.groupItemTotal
return indexOffset - footerOffset + this.groupItemTotal
}
private getHeaderOffset(index: number) {
let headerOffset = this.headerIndex % this.groupItemTotal
let indexOffset = index % this.groupItemTotal
return headerOffset - indexOffset + this.groupItemTotal
}
private offsetToHeader(index: number) {
var offset = 0
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
offset = this.getHeaderOffset(index)
} else {
offset = this.getFooterOffset(index)
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
offset = this.getHeaderOffset(index)
} else {
offset = this.getFooterOffset(index)
}
}
offset -= this.groupItemTotal
for (let i = 0; i < offset; i++) {
this.pushToHeader(true)
}
}
private offsetToFooter(index: number) {
var offset = 0
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
offset = this.getFooterOffset(index)
} else {
offset = this.getHeaderOffset(index)
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
offset = this.getFooterOffset(index)
} else {
offset = this.getHeaderOffset(index)
}
}
offset -= this.groupItemTotal
for (let i = 0; i < offset; i++) {
this.pushToFooter(true)
}
}
private resetIndexStartToEnd(index: number) {
for (let i = 0; i < this.node.children.length; i++) {
const child: any = this.node.children[i];
child["__index"] = index
index++
if (this.headerLoop || this.footerLoop) {
if (index < 0 || index >= this.itemTotal) {
index = 0
}
}
this.notifyRefreshItem(child)
}
}
private resetIndexEndToStart(index: number) {
for (let i = this.node.children.length - 1; i >= 0; i--) {
const child: any = this.node.children[i];
child["__index"] = index
index--
if (this.headerLoop || this.footerLoop) {
if (index < 0) {
index = this.itemTotal - 1
}
}
this.notifyRefreshItem(child)
}
}
/** 跳转到指定索引位置 */
scrollToIndex(index: number, timeInSecond?: number, boundary?: Vec3, reverse: boolean = false) {
if (isNaN(index) || index < 0 || index > this.itemTotal - 1) return
this.scrollView.stopAutoScroll()
if (this.isPageView) {
this.scrollView.savePageIndex(index)
}
var child = this.node.children.find((item: any) => item["__index"] == index)
var nearFooter = this.isNearFooter(index)
this.stretchLock.index = index
this.stretchLock.timeInSecond = timeInSecond
this.stretchLock.boundary = boundary
this.stretchLock.reverse = reverse
if (!child) {
if (index == 0) {
this.pushToHeader()
}
if (index == this.itemTotal - 1) {
this.pushToFooter()
}
var flag = this.vertical && this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM || !this.vertical && this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT
if (nearFooter) {
this.offsetToFooter(index)
flag ? this.resetIndexEndToStart(index) : this.resetIndexStartToEnd(index)
} else {
this.offsetToHeader(index)
flag ? this.resetIndexStartToEnd(index) : this.resetIndexEndToStart(index)
}
child = this.node.children.find((item: any) => item["__index"] == index)
}
if (!child) return
let itemPos = child.getPosition().clone()
if (!this.autoCenter) {
if (this.vertical) {
if (this.indexVerticalAxisDirection == IndexVerticalAxisDirection.TOP) {
if (!reverse) {
itemPos.y = this.getItemYMax(child._uiProps.uiTransformComp!) + this.paddingTop
} else {
itemPos.y = this.getItemYMin(child._uiProps.uiTransformComp!) - this.paddingBottom
}
} else {
if (!reverse) {
itemPos.y = this.getItemYMin(child._uiProps.uiTransformComp!) - this.paddingBottom
} else {
itemPos.y = this.getItemYMax(child._uiProps.uiTransformComp!) + this.paddingTop
}
}
} else {
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.LEFT) {
if (!reverse) {
itemPos.x = this.getItemXMin(child._uiProps.uiTransformComp!) - this.paddingLeft
} else {
itemPos.x = this.getItemXMax(child._uiProps.uiTransformComp!) + this.paddingRight
}
} else {
if (!reverse) {
itemPos.x = this.getItemXMax(child._uiProps.uiTransformComp!) + this.paddingRight
} else {
itemPos.x = this.getItemXMin(child._uiProps.uiTransformComp!) - this.paddingLeft
}
}
}
}
let worldPos = this.transform?.convertToWorldSpaceAR(itemPos)!
let localPos = this.view.convertToNodeSpaceAR(worldPos)
var multiple
if (!this.autoCenter && boundary) {
multiple = boundary
} else {
multiple = this.getCenterAnchor(child._uiProps.uiTransformComp!, this.centerPosition)
}
localPos.multiply(new Vec3(-1, -1, 1)).add(multiple)
this.scrollView.scrollToAny(localPos, timeInSecond, true)
}
protected async onViewSizeChange() {
this.isRestart = true
this.createItems(this.currentCreateItemTotal)
this.resetChilds(true)
this.scrollToHeader()
for (let i = 0; i < this.node.children.length; i++) {
const child: any = this.node.children[i];
const transform = child._uiProps.uiTransformComp!
this.setAndSaveSizeAndScale(transform)
}
this.isRestart = false
}
protected setAndSaveSizeAndScale(item: UITransform) {
item.setContentSize(this.getItemSize(item));
(item.node as any)["__size"] = item.contentSize.clone();
(item.node as any)["__scale"] = item.node.getScale().clone();
}
/** 根据centerAnchor计算自动居中的真实位置 */
protected getCenterAnchor(item: UITransform, center: Vec3) {
var pos = center.clone()
if (this.vertical) {
let anchor = item.height! * this.centerAnchor.y
let origin = item.height! * item.anchorY!
pos.y -= anchor - origin
} else {
let anchor = item.width! * this.centerAnchor.x
let origin = item.width! * item.anchorX!
pos.x += anchor - origin
}
return pos
}
/** 滚动即将结束时 跑自动居中的逻辑 */
protected soonFinish() {
if (!this.autoCenter) return
if (this.scrollView.pullRefresh) return
this.scrollView.stopAutoScroll()
var findedPos = new Vec3(999999, 999999)
for (let i = 0; i < this.node.children.length; i++) {
const child = this.node.children[i];
let worldPos = this.transform?.convertToWorldSpaceAR(child.position)!
let localPos = this.view.convertToNodeSpaceAR(worldPos)
let map = { width: false, height: false }
var multiple = this.getCenterAnchor(child._uiProps.uiTransformComp!, this.centerPosition)
let newLocalPos = localPos.subtract(multiple)
map.width = Math.abs(newLocalPos.x) < Math.abs(findedPos.x)
map.height = Math.abs(newLocalPos.y) < Math.abs(findedPos.y)
if (this.vertical && map.height) {
findedPos = newLocalPos
} else if (!this.vertical && map.width) {
findedPos = newLocalPos
}
}
findedPos.multiply(new Vec3(-1, -1, 1))
this.scrollView.scrollToAny(findedPos, this.centerTime)
}
/** 根据groupItemTotal和View可容纳的尺寸 来平均分配Item该有的尺寸 */
protected getItemSize(item: UITransform): Size {
let size = new Size()
if (this.vertical) {
let spacing = this.spacingX * (this.groupItemTotal - 1)
size.width = (this.accommodWidth - spacing) / this.groupItemTotal
size.height = item.height
} else {
let spacing = this.spacingY * (this.groupItemTotal - 1)
size.height = (this.accommodHeight - spacing) / this.groupItemTotal
size.width = item.width
}
return size
}
/** 获取Item的YMax */
protected getItemYMax(item: UITransform | null): number {
if (!item) return 0
let height = this.getScaleHeight(item) * (1 - item.anchorY)
return item.node.position.y + height
}
/** 获取Item的YMin */
protected getItemYMin(item: UITransform | null): number {
if (!item) return 0
let height = this.getScaleHeight(item) * item.anchorY
return item.node.position.y - height
}
/** 获取Item的XMax */
protected getItemXMax(item: UITransform | null): number {
if (!item) return 0
let width = this.getScaleWidth(item) * (1 - item.anchorX)
return item.node.position.x + width
}
/** 获取Item的XMin */
protected getItemXMin(item: UITransform | null): number {
if (!item) return 0
let width = this.getScaleWidth(item) * item.anchorX
return item.node.position.x - width
}
/** 获取一组Item中起始位置X */
protected getStartX(item: UITransform | null): number {
if (!item) return 0
var x = 0
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
let width = this.getScaleWidth(item) * item.anchorX
x = this.viewStartPoint.x + width
} else {
let width = this.getScaleWidth(item) * (1 - item.anchorX)
x = this.viewStartPoint.x - width
}
return x
}
/** 获取一组Item中结束位置X */
protected getEndX(item: UITransform | null): number {
if (!item) return 0
var x = 0
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
let width = this.getScaleWidth(item) * (1 - item.anchorX)
x = -this.viewStartPoint.x - width - this.paddingRight + this.paddingLeft
} else {
let width = this.getScaleWidth(item) * item.anchorX
x = -this.viewStartPoint.x + width + this.paddingLeft - this.paddingRight
}
return x
}
/** 获取一组Item中起始位置Y */
protected getStartY(item: UITransform | null): number {
if (!item) return 0
var y = 0
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
let height = this.getScaleHeight(item) * (1 - item.anchorY)
y = this.viewStartPoint.y - height
} else {
let height = this.getScaleHeight(item) * item.anchorY
y = this.viewStartPoint.y + height
}
return y
}
/** 获取一组Item中结束位置Y */
protected getEndY(item: UITransform | null): number {
if (!item) return 0
var y = 0
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
let height = this.getScaleHeight(item) * item.anchorY
y = -this.viewStartPoint.y + height + this.paddingBottom - this.paddingTop
} else {
let height = this.getScaleHeight(item) * (1 - item.anchorY)
y = -this.viewStartPoint.y - height - this.paddingTop + this.paddingBottom
}
return y
}
/** relative的顶部是否有也容纳空间 */
protected isAccommodateByTop(relative: UITransform) {
var max = this.getItemYMax(relative)
return max + this.paddingTop < this.accommodHeight * 0.5
}
/** relative的底部是否有也容纳空间 */
protected isAccommodateByBottom(relative: UITransform) {
var min = this.getItemYMin(relative)
return min - this.paddingBottom > this.accommodHeight * -0.5
}
/** relative的左侧是否有也容纳空间 */
protected isAccommodateByLeft(relative: UITransform) {
var min = this.getItemXMin(relative)
return min - this.paddingLeft > this.accommodWidth * -0.5
}
/** relative的右侧是否有也容纳空间 */
protected isAccommodateByRight(relative: UITransform) {
var max = this.getItemXMax(relative)
return max + this.paddingRight < this.accommodWidth * 0.5
}
/** relative的左侧位置 */
protected getRelativeByLeft(item: UITransform, relative: UITransform): number {
var min = this.getItemXMin(relative)
return min - this.spacingX - this.getScaleWidth(item) * (1 - item.anchorX)
}
/** relative的右侧位置 */
protected getRelativeByRight(item: UITransform, relative: UITransform): number {
var max = this.getItemXMax(relative)
return max + this.spacingX + this.getScaleWidth(item) * item.anchorX
}
/** relative的顶部位置 */
protected getRelativeByTop(item: UITransform, relative: UITransform): number {
var max = this.getItemYMax(relative)
return max + this.spacingY + this.getScaleHeight(item) * item.anchorY
}
/** relative的底部位置 */
protected getRelativeByBottom(item: UITransform, relative: UITransform): number {
var min = this.getItemYMin(relative)
return min - this.spacingY - this.getScaleHeight(item) * (1 - item.anchorY)
}
/** 设置Item的坐标位置 */
protected setItemPosition(item: UITransform, relative: UITransform, reverse: boolean = false, isHeader: boolean = false) {
var pos = new Vec3()
if (isHeader) {
pos.x = this.getStartX(item)
pos.y = this.getStartY(item)
} else {
if (this.vertical) {
pos = this.getVerticalRelativePosition(item, relative, reverse)
} else {
pos = this.getHorizontalRelativePosition(item, relative, reverse)
}
}
item.node.setPosition(pos)
}
/** 计算垂直模式的Item应该的位置 */
protected getVerticalRelativePosition(item: UITransform, relative: UITransform, reverse: boolean) {
var pos = new Vec3()
var isAccommodate = false
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
isAccommodate = !reverse ? this.isAccommodateByRight(relative) : this.isAccommodateByLeft(relative)
} else {
isAccommodate = !reverse ? this.isAccommodateByLeft(relative) : this.isAccommodateByRight(relative)
}
// 横轴
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (!reverse) {
pos.x = isAccommodate ? this.getRelativeByRight(item, relative) : this.getStartX(item)
} else {
pos.x = isAccommodate ? this.getRelativeByLeft(item, relative) : this.getEndX(item)
}
} else {
if (!reverse) {
pos.x = isAccommodate ? this.getRelativeByLeft(item, relative) : this.getStartX(item)
} else {
pos.x = isAccommodate ? this.getRelativeByRight(item, relative) : this.getEndX(item)
}
}
// 纵轴
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (!reverse) {
pos.y = isAccommodate ? relative.node.position.y : this.getRelativeByBottom(item, relative)
} else {
pos.y = isAccommodate ? relative.node.position.y : this.getRelativeByTop(item, relative)
}
} else {
if (!reverse) {
pos.y = isAccommodate ? relative.node.position.y : this.getRelativeByTop(item, relative)
} else {
pos.y = isAccommodate ? relative.node.position.y : this.getRelativeByBottom(item, relative)
}
}
return pos
}
/** 计算水平模式的Item应该的位置 */
protected getHorizontalRelativePosition(item: UITransform, relative: UITransform, reverse: boolean) {
var pos = new Vec3()
var isAccommodate = false
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
isAccommodate = !reverse ? this.isAccommodateByBottom(relative) : this.isAccommodateByTop(relative)
} else {
isAccommodate = !reverse ? this.isAccommodateByTop(relative) : this.isAccommodateByBottom(relative)
}
// 纵轴
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (!reverse) {
pos.y = isAccommodate ? this.getRelativeByBottom(item, relative) : this.getStartY(item)
} else {
pos.y = isAccommodate ? this.getRelativeByTop(item, relative) : this.getEndY(item)
}
} else {
if (!reverse) {
pos.y = isAccommodate ? this.getRelativeByTop(item, relative) : this.getStartY(item)
} else {
pos.y = isAccommodate ? this.getRelativeByBottom(item, relative) : this.getEndY(item)
}
}
// 横轴
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (!reverse) {
pos.x = isAccommodate ? relative.node.position.x : this.getRelativeByRight(item, relative)
} else {
pos.x = isAccommodate ? relative.node.position.x : this.getRelativeByLeft(item, relative)
}
} else {
if (!reverse) {
pos.x = isAccommodate ? relative.node.position.x : this.getRelativeByLeft(item, relative)
} else {
pos.x = isAccommodate ? relative.node.position.x : this.getRelativeByRight(item, relative)
}
}
return pos
}
/** 当数据长度发生变化时 计算item应该怎么排列 */
protected refreshItems(offset: number, refreshLastItem: boolean = false) {
if (offset < 0) {
var prev = this.header!
if (this.contentSize.height == this.view.height) {
for (let i = 0; i < this.node.children.length; i++) {
const child = this.node.children[i]
this.setItemPosition(child._uiProps.uiTransformComp!, prev, false, i == 0)
prev = child._uiProps.uiTransformComp!
}
} else {
for (let i = 0; i < -offset; i++) {
if (this.headerLoop) {
this.pushToHeader()
} else if (this.footerLoop) {
this.pushToHeader()
} else {
if (this.vertical && this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM || this.horizontal && this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
this.pushToHeader(true)
this.pushToFooter()
} else {
this.pushToFooter(true)
this.pushToHeader()
}
}
}
}
let startIndex = this.headerIndex > 0 ? this.headerIndex : 0
if (startIndex + this.node.children.length > this.itemTotal) {
startIndex += offset
}
if (startIndex < 0) startIndex = 0
for (let i = 0; i < this.node.children.length; i++) {
const child: any = this.node.children[i];
if (this.headerLoop || this.footerLoop) {
if (startIndex > this.itemTotal - 1) {
startIndex = 0
}
}
child["__index"] = startIndex
startIndex++
if (refreshLastItem) {
this.notifyRefreshItem(child)
}
}
this.scrollView.stopAutoScroll()
this.scrollView.startAutoScroll()
} else {
for (let i = 0; i < this.node.children.length; i++) {
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
this.pushToFooter()
} else {
this.pushToHeader()
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
this.pushToFooter()
} else {
this.pushToHeader()
}
}
}
}
}
protected createItems(count: number, refreshLastItem: boolean = false) {
// 有多余的item 需要删除 不处理
if (this.node.children.length > count) {
this.removeItems(count)
return
}
if (!this.needAddPrefab()) {
// 已经固定item总数 不处理
if (this._maxPrefabTotal > 0 && this._maxPrefabTotal == this.node.children.length) {
return
}
}
let total = count - this.node.children.length //计算当前应该创建的总数
for (let i = 0; i < total; i++) {
let child: any = instantiate(this.prefab)
const transform = child._uiProps.uiTransformComp
this.setAndSaveSizeAndScale(transform)
child["__index"] = this.node.children.length
this.node.addChild(child)
var reverse = false
var index = this.node.children.length - 2
var relative
if (child["__index"] == 0) {
relative = this.footer!
} else {
relative = this.node.children[index]._uiProps.uiTransformComp!
}
child.on(Node.EventType.SIZE_CHANGED, () => { this.onChangeChildSize(transform) }, this, true)
child.on(Node.EventType.TRANSFORM_CHANGED, (type: any) => { this.onChangeChildScale(type, transform) }, this, true)
if (refreshLastItem) {
this.notifyRefreshItem(child)
}
this.setItemPosition(child._uiProps.uiTransformComp, relative, reverse, child["__index"] == 0)
if (!this.needAddPrefab()) {
this._maxPrefabTotal = this.node.children.length
console.log("已固定item数量", this._maxPrefabTotal)
break
}
}
}
protected needAddPrefab() {
const self = this.vertical ? this.contentSize.height : this.contentSize.width
if (self > 0) {
// 当尺寸改变时 重新计算prefab的数量
const view = this.vertical ? this.view.height : this.view.width
if (self < view * this.multiple) {
return true
}
}
return false
}
protected async onChangeChildSize(item: UITransform) {
const node: any = item.node
if (this.groupItemTotal > 1) {
const __size = node["__size"]
item.setContentSize(__size)
console.warn("表格布局不支持动态修改 Size,如果你非要修改,那你把我注释掉看效果")
return
}
if (this.stretchLock.index == node["__index"]) {
this.scrollToIndex(this.stretchLock.index!, this.stretchLock.timeInSecond, this.stretchLock.boundary, this.stretchLock.reverse)
}
this.resetStrectchItems()
}
protected async onChangeChildScale(type: any, item: UITransform) {
if (type !== Node.TransformBit.SCALE) {
return
}
if (!this.affectedByScale) return
const node: any = item.node
if (this.groupItemTotal > 1) {
const __scale = node["__scale"]
item.node.setScale(__scale)
console.warn("表格布局不支持动态修改 Scale,如果你非要修改,那你把我注释掉看效果")
return
}
if (this.stretchLock.index == node["__index"]) {
this.scrollToIndex(this.stretchLock.index!, this.stretchLock.timeInSecond, this.stretchLock.boundary, this.stretchLock.reverse)
}
this.resetStrectchItems()
}
protected resetStrectchItems() {
if (!isNaN(this.stretchLock.index!)) {
const index = this.node.children.findIndex((item: any) => item["__index"] == this.stretchLock.index)
if (index != -1) {
for (let i = index; i >= 0; i--) {
const item = this.node.children[i];
if (i == index) continue
if (i < index) {
this.setItemPosition(item._uiProps.uiTransformComp!, this.node.children[i + 1]._uiProps.uiTransformComp!, true)
}
}
for (let i = index; i < this.node.children.length; i++) {
const item = this.node.children[i];
if (i == index) continue
this.setItemPosition(item._uiProps.uiTransformComp!, this.node.children[i - 1]._uiProps.uiTransformComp!)
}
return
}
}
if (this.scrollDirection == ScrollDirection.HEADER) {
this.unschedule(this.stretchToFooter)
this.scheduleOnce(this.stretchToFooter)
} else {
this.unschedule(this.stretchToHeader)
this.scheduleOnce(this.stretchToHeader)
}
}
private stretchToHeader() {
for (let i = this.node.children.length - 1; i >= 0; i--) {
const item = this.node.children[i];
if (i == this.node.children.length - 1) continue
this.setItemPosition(item._uiProps.uiTransformComp!, this.node.children[i + 1]._uiProps.uiTransformComp!, true)
}
}
private stretchToFooter() {
for (let i = 0; i < this.node.children.length; i++) {
const item = this.node.children[i];
if (i == 0) continue
this.setItemPosition(item._uiProps.uiTransformComp!, this.node.children[i - 1]._uiProps.uiTransformComp!)
}
}
/** 删除多余的item */
protected removeItems(count: number) {
// 有多余的item 需要删除
let length = this.node.children.length - count
// 删除掉多余的item
for (let i = 0; i < length; i++) {
var child = this.node.children[this.node.children.length - 1]
child.off(Node.EventType.SIZE_CHANGED)
child.off(Node.EventType.TRANSFORM_CHANGED)
this.node.removeChild(child)
child.destroy()
}
}
protected addEventListener() {
this.node.on(SystemEventType.TRANSFORM_CHANGED, this.onPositionChanged, this)
}
protected removeEventListener() {
this.node.off(SystemEventType.TRANSFORM_CHANGED, this.onPositionChanged, this)
}
/** 重新计算当前所有Item的位置 */
protected resetChilds(start: boolean = false) {
if (this.vertical && this.fixedItemHeight <= this.view.height || !this.vertical && this.fixedItemWidth <= this.view.width) {
let x = this.getStartX(this.header)
let y = this.getStartY(this.header)
this.header?.node.setPosition(new Vec3(x, y))
}
if (start) {
if (this.vertical) {
let x = this.getStartX(this.header)
this.header?.node.setPosition(new Vec3(x, this.header.node.position.y))
} else {
let y = this.getStartY(this.header)
this.header?.node.setPosition(new Vec3(this.header.node.position.x, y))
}
}
this.stretchToFooter()
if (!start) {
this.scrollView.startAutoScroll()
}
}
protected onTouchBegin() {
this.stretchLock = {}
}
protected getUsedScaleValue(value: number) {
return this.affectedByScale ? Math.abs(value) : 1;
}
protected getScaleWidth(trans: UITransform | null): number {
if (!trans) return 0
const size = (trans.node as any)["__runtime_size"]
const width = size ? size.width : trans.width
return width * this.getUsedScaleValue(trans.node.scale.x)
}
protected getScaleHeight(trans: UITransform | null): number {
if (!trans) return 0
const size = (trans.node as any)["__runtime_size"]
const height = size ? size.height : trans.height
return height * this.getUsedScaleValue(trans.node.scale.y)
}
protected onPositionChanged() {
if (this.isRestart) return
if (this.vertical) {
if (this.scrollView.prevLocation.y < this.scrollView.location.y) {
this.scrollDirection = ScrollDirection.FOOTER
} else if (this.scrollView.prevLocation.y > this.scrollView.location.y) {
this.scrollDirection = ScrollDirection.HEADER
} else {
this.scrollDirection = ScrollDirection.NONE
}
} else {
if (this.scrollView.prevLocation.x > this.scrollView.location.x) {
this.scrollDirection = ScrollDirection.FOOTER
} else if (this.scrollView.prevLocation.x < this.scrollView.location.x) {
this.scrollDirection = ScrollDirection.HEADER
} else {
this.scrollDirection = ScrollDirection.NONE
}
}
if (this.vertical) {
for (let i = 0; i < this.node.children.length; i++) {
let isOfBoundary = Math.abs(this.prevPos.y - this.node.position.y) > EPSILON
if (!isOfBoundary) continue
if (this.prevPos.y < this.node.position.y) {
this.pushToFooter()
} else if (this.prevPos.y > this.node.position.y) {
this.pushToHeader()
}
}
} else {
for (let i = 0; i < this.node.children.length; i++) {
let isOfBoundary = Math.abs(this.prevPos.x - this.node.position.x) > EPSILON
if (!isOfBoundary) continue
if (this.prevPos.x > this.node.position.x) {
this.pushToFooter()
} else if (this.prevPos.x < this.node.position.x) {
this.pushToHeader()
}
}
}
this.prevPos = this.node.position.clone()
}
/** 向尾部填充 force如果为true 则强制填充 */
protected pushToFooter(force: boolean = false) {
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (force || this.headerBoundary - this.paddingTop > this.viewHeaderBoundary + this.header?.height!) {
this.pushToFooterHandler()
}
} else {
if (force || this.footerBoundary - this.paddingTop > this.viewHeaderBoundary + this.header?.height!) {
this.pushToHeaderHandler()
}
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (force || this.headerBoundary + this.paddingLeft < this.viewHeaderBoundary - this.header?.width!) {
this.pushToFooterHandler()
}
} else {
if (force || this.footerBoundary + this.paddingLeft < this.viewHeaderBoundary - this.header?.width!) {
this.pushToHeaderHandler()
}
}
}
}
/** 向头部填充 force如果为true 则强制填充 */
protected pushToHeader(force: boolean = false) {
if (this.vertical) {
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (force || this.footerBoundary + this.paddingBottom < this.viewFooterBoundary - this.footer?.height!) {
this.pushToHeaderHandler()
}
} else {
if (force || this.headerBoundary + this.paddingBottom < this.viewFooterBoundary - this.footer?.height!) {
this.pushToFooterHandler()
}
}
} else {
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (force || this.footerBoundary - this.paddingRight > this.viewFooterBoundary + this.footer?.width!) {
this.pushToHeaderHandler()
}
} else {
if (force || this.headerBoundary - this.paddingRight > this.viewFooterBoundary + this.footer?.width!) {
this.pushToFooterHandler()
}
}
}
}
protected pushToFooterHandler() {
var node: any = this.header?.node
let loop
if (this.vertical) {
loop = this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM ? this.footerLoop : this.headerLoop
} else {
loop = this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT ? this.footerLoop : this.headerLoop
}
if (loop) {
if (this.footerIndex >= this.itemTotal - 1) {
node["__index"] = 0
} else {
node["__index"] = this.footerIndex + 1
}
} else {
if (!this.footer || this.footerIndex >= this.itemTotal - 1) return
node["__index"] = this.footerIndex + 1
}
if (node["__index"] >= 0 && node["__index"] < this.currentCreateItemTotal) {
this.notifyRefreshItem(node)
}
this.setItemPosition(this.header!, this.footer!)
this.header?.node.setSiblingIndex(this.node.children.length)
}
protected pushToHeaderHandler() {
var node: any = this.footer?.node
let loop
if (this.vertical) {
loop = this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM ? this.headerLoop : this.footerLoop
} else {
loop = this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT ? this.headerLoop : this.footerLoop
}
// 对其头部
if (!loop && this.headerIndex == 0) {
// 判断是否是起始位置
var accommodate
if (this.vertical) {
accommodate = this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT ? this.isAccommodateByLeft(this.header!) : this.isAccommodateByRight(this.header!)
} else {
accommodate = this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM ? this.isAccommodateByTop(this.header!) : this.isAccommodateByBottom(this.header!)
}
if (accommodate) {
this.resetChilds(true)
}
}
if (loop) {
if (this.headerIndex == 0) {
node["__index"] = this.itemTotal - 1
} else {
node["__index"] = this.headerIndex - 1
}
} else {
if (!this.header || this.headerIndex == 0) return
node["__index"] = this.headerIndex - 1
}
if (node["__index"] >= 0 && node["__index"] < this.currentCreateItemTotal) {
this.notifyRefreshItem(node)
}
this.setItemPosition(this.footer!, this.header!, true)
this.footer?.node.setSiblingIndex(0)
}
/** 通知给定的node刷新数据 */
protected notifyRefreshItem(target: Node) {
EventHandler.emitEvents(this.refreshItemEvents, target, (target as any)['__index'])
}
}