2022-08-26 16:48:17 +08:00

1460 lines
51 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 UISuperScrollview from "./UISuperScrollView";
const { ccclass, property } = cc._decorator;
const EPSILON = 1e-4;
enum Type {
HORIZONTAL = 0,
VERTICAL = 1,
}
cc.Enum(Type);
enum VerticalAxisDirection {
TOP_TO_BOTTOM = 0,
BOTTOM_TO_TOP = 1
}
cc.Enum(VerticalAxisDirection);
enum HorizontalAxisDirection {
LEFT_TO_RIGHT = 0,
RIGHT_TO_LEFT = 1
}
cc.Enum(HorizontalAxisDirection);
enum ScrollDirection {
NONE = 0,
HEADER = 1,
FOOTER = 2,
}
enum IndexVerticalAxisDirection {
TOP = 0,
BOTTOM = 1,
}
cc.Enum(IndexVerticalAxisDirection);
enum IndexHorizontalAxisDirection {
LEFT = 0,
RIGHT = 1
}
cc.Enum(IndexHorizontalAxisDirection);
@ccclass
export default class UISuperLayout extends cc.Component {
static VerticalAxisDirection = VerticalAxisDirection;
static HorizontalAxisDirection = HorizontalAxisDirection;
@property(UISuperScrollview) scrollView: UISuperScrollview = null;
@property(cc.Node) view: cc.Node = null;
@property(cc.Prefab) prefab: cc.Prefab = null;
@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: cc.PageViewIndicator,
visible: function () { return (this as any).isPageView; }
}) indicator: cc.PageViewIndicator = null;
@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: cc.Component.EventHandler,
visible: function () { return (this as any).isPageView; }
}) pageEvents: cc.Component.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: cc.Node,
tooltip: "自动居中的参考节点如果为空、则默认选择View中心",
visible: function () { return (this as any).autoCenter; }
}) centerNode: cc.Node = null;
@property({
tooltip: "自动居中时、Item的居中锚点",
// visible: function () { return (this as any).autoCenter; }
}) centerAnchor: cc.Vec2 = new cc.Vec2(.5, .5);
@property({ tooltip: "上/左 无限循环" }) headerLoop: boolean = false;
@property({ tooltip: "下/右 无限循环" }) footerLoop: boolean = false;
@property(cc.Component.EventHandler) refreshItemEvents: cc.Component.EventHandler[] = [];
private stretchLock: {
index?: number,
timeInSecond?: number,
boundary?: cc.Vec2,
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(): cc.Node { return this.node; }
/** View 可容纳的宽度 */
get accommodWidth() {
return this.view.width - this.paddingLeft - this.paddingRight;
}
/** View 可容纳的高度 */
get accommodHeight() {
return this.view.height - this.paddingTop - this.paddingBottom;
}
/** 头部的节点 */
get header(): cc.Node {
if (this.node.children.length == 0) return null;
return this.node.children[0];
}
/** 底部的节点 */
get footer(): cc.Node {
if (this.node.children.length == 0) return null;
return this.node.children[this.node.children.length - 1];
}
/** 头部索引 */
get headerIndex(): number {
if (!this.header) return -1;
let node: any = this.header;
return node["__index"];
}
/** 底部索引 */
get footerIndex(): number {
if (!this.footer) return -1;
let node: any = this.footer;
return node["__index"];
}
/** Item起始位置 */
get viewStartPoint(): cc.Vec3 {
let pos = new cc.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.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.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(): cc.Size {
if (this.node.children.length == 0) return this.view.getContentSize();
let size = new cc.Size(this.view.getContentSize().width, this.view.getContentSize().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.getContentSize().width) {
size.width = this.view.getContentSize().width;
}
if (size.height < this.view.getContentSize().height) {
size.height = this.view.getContentSize().height;
}
return size;
}
private prevPos: cc.Vec3 = new cc.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: cc.Vec3;
/** 自动居中的参考位置 */
get centerPosition(): cc.Vec3 {
if (!this._centerPosition) {
this._centerPosition = new cc.Vec3();
if (this.autoCenter) {
if (this.centerNode) {
let worldPos = this.centerNode.parent.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 cc.Vec2(.5, .5));
this.transform.setContentSize(this.view.getContentSize());
this.node.setPosition(cc.Vec3.ZERO);
if (this.isPageView) this.autoCenter = false;
this.scrollView.view.on(cc.Node.EventType.SIZE_CHANGED, this.onViewSizeChange, this);
Object.defineProperty(this.transform, "getContentSize", { get: () => () => this.contentSize });
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 就不会刷新所有数据
*/
public CreateItem(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: cc.Node, size: cc.Size) {
if (this.groupItemTotal > 1) return;
if (!node || !size) return;
// 20220209 開啟會導致對應位置的組件被重置錯誤Size by豆豆
// (node as any)["__runtime_size"] = size;
this.onChangeChildSize(node);
}
/** 自动居中到最近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 cc.Vec2(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 cc.Vec2(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?: cc.Vec2, 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) + this.paddingTop;
} else {
itemPos.y = this.getItemYMin(child) - this.paddingBottom;
}
} else {
if (!reverse) {
itemPos.y = this.getItemYMin(child) - this.paddingBottom;
} else {
itemPos.y = this.getItemYMax(child) + this.paddingTop;
}
}
} else {
if (this.indexHorizontalAxisDirection == IndexHorizontalAxisDirection.LEFT) {
if (!reverse) {
itemPos.x = this.getItemXMin(child) - this.paddingLeft;
} else {
itemPos.x = this.getItemXMax(child) + this.paddingRight;
}
} else {
if (!reverse) {
itemPos.x = this.getItemXMax(child) + this.paddingRight;
} else {
itemPos.x = this.getItemXMin(child) - 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, this.centerPosition);
}
localPos.x *= -1;
localPos.y *= -1;
localPos = localPos.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;
this.setAndSaveSizeAndScale(transform);
}
this.isRestart = false;
}
protected setAndSaveSizeAndScale(item: cc.Node) {
item.setContentSize(this.getItemSize(item));
item["__size"] = item.getContentSize().clone();
item["__scale"] = cc.v2(item.scaleX, item.scaleY);
}
/** 根据centerAnchor计算自动居中的真实位置 */
protected getCenterAnchor(item: cc.Node, center: cc.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 cc.Vec2(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, this.centerPosition);
localPos.x -= multiple.x;
localPos.y -= multiple.y;
let newLocalPos = localPos;
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 = cc.v2(newLocalPos.x, newLocalPos.y);
} else if (!this.vertical && map.width) {
findedPos = cc.v2(newLocalPos.x, newLocalPos.y);
}
}
findedPos.x *= -1;
findedPos.y *= -1;
this.scrollView.scrollToAny(findedPos, this.centerTime);
}
/** 根据groupItemTotal和View可容纳的尺寸 来平均分配Item该有的尺寸 */
protected getItemSize(item: cc.Node): cc.Size {
let size = new cc.Size(0, 0);
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: cc.Node | null): number {
if (!item) return 0;
let height = this.getScaleHeight(item) * (1 - item.anchorY);
return item.position.y + height;
}
/** 获取Item的YMin */
protected getItemYMin(item: cc.Node | null): number {
if (!item) return 0;
let height = this.getScaleHeight(item) * item.anchorY;
return item.position.y - height;
}
/** 获取Item的XMax */
protected getItemXMax(item: cc.Node | null): number {
if (!item) return 0;
let width = this.getScaleWidth(item) * (1 - item.anchorX);
return item.position.x + width;
}
/** 获取Item的XMin */
protected getItemXMin(item: cc.Node | null): number {
if (!item) return 0;
let width = this.getScaleWidth(item) * item.anchorX;
return item.position.x - width;
}
/** 获取一组Item中起始位置X */
protected getStartX(item: cc.Node | 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: cc.Node | 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: cc.Node | 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: cc.Node | 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: cc.Node) {
var max = this.getItemYMax(relative);
return max + this.paddingTop < this.accommodHeight * 0.5;
}
/** relative的底部是否有也容纳空间 */
protected isAccommodateByBottom(relative: cc.Node) {
var min = this.getItemYMin(relative);
return min - this.paddingBottom > this.accommodHeight * -0.5;
}
/** relative的左侧是否有也容纳空间 */
protected isAccommodateByLeft(relative: cc.Node) {
var min = this.getItemXMin(relative);
return min - this.paddingLeft > this.accommodWidth * -0.5;
}
/** relative的右侧是否有也容纳空间 */
protected isAccommodateByRight(relative: cc.Node) {
var max = this.getItemXMax(relative);
return max + this.paddingRight < this.accommodWidth * 0.5;
}
/** relative的左侧位置 */
protected getRelativeByLeft(item: cc.Node, relative: cc.Node): number {
var min = this.getItemXMin(relative);
return min - this.spacingX - this.getScaleWidth(item) * (1 - item.anchorX);
}
/** relative的右侧位置 */
protected getRelativeByRight(item: cc.Node, relative: cc.Node): number {
var max = this.getItemXMax(relative);
return max + this.spacingX + this.getScaleWidth(item) * item.anchorX;
}
/** relative的顶部位置 */
protected getRelativeByTop(item: cc.Node, relative: cc.Node): number {
var max = this.getItemYMax(relative);
return max + this.spacingY + this.getScaleHeight(item) * item.anchorY;
}
/** relative的底部位置 */
protected getRelativeByBottom(item: cc.Node, relative: cc.Node): number {
var min = this.getItemYMin(relative);
return min - this.spacingY - this.getScaleHeight(item) * (1 - item.anchorY);
}
/** 设置Item的坐标位置 */
protected setItemPosition(item: cc.Node, relative: cc.Node, reverse: boolean = false, isHeader: boolean = false) {
var pos = new cc.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.setPosition(pos);
}
/** 计算垂直模式的Item应该的位置 */
protected getVerticalRelativePosition(item: cc.Node, relative: cc.Node, reverse: boolean) {
var pos = new cc.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.position.y : this.getRelativeByBottom(item, relative);
} else {
pos.y = isAccommodate ? relative.position.y : this.getRelativeByTop(item, relative);
}
} else {
if (!reverse) {
pos.y = isAccommodate ? relative.position.y : this.getRelativeByTop(item, relative);
} else {
pos.y = isAccommodate ? relative.position.y : this.getRelativeByBottom(item, relative);
}
}
return pos;
}
/** 计算水平模式的Item应该的位置 */
protected getHorizontalRelativePosition(item: cc.Node, relative: cc.Node, reverse: boolean) {
var pos = new cc.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.position.x : this.getRelativeByRight(item, relative);
} else {
pos.x = isAccommodate ? relative.position.x : this.getRelativeByLeft(item, relative);
}
} else {
if (!reverse) {
pos.x = isAccommodate ? relative.position.x : this.getRelativeByLeft(item, relative);
} else {
pos.x = isAccommodate ? relative.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, prev, false, i == 0);
prev = child;
}
} 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 = cc.instantiate(this.prefab);
const transform = child;
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];
}
child.on(cc.Node.EventType.SIZE_CHANGED, () => { this.onChangeChildSize(transform); }, this, true);
child.on(cc.Node.EventType.SCALE_CHANGED, (type: any) => { this.onChangeChildScale(transform); }, this, true);
if (refreshLastItem) {
this.notifyRefreshItem(child);
}
this.setItemPosition(child, 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: cc.Node) {
const node: any = item;
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(item: cc.Node) {
if (!this.affectedByScale) return;
const node: any = item;
if (this.groupItemTotal > 1) {
const __scale = node["__scale"];
item.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, this.node.children[i + 1], true);
}
}
for (let i = index; i < this.node.children.length; i++) {
const item = this.node.children[i];
if (i == index) continue;
this.setItemPosition(item, this.node.children[i - 1]);
}
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, this.node.children[i + 1], 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, this.node.children[i - 1]);
}
}
/** 删除多余的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(cc.Node.EventType.SIZE_CHANGED);
child.off(cc.Node.EventType.SCALE_CHANGED);
this.node.removeChild(child);
child.destroy();
}
}
protected addEventListener() {
this.node.on(cc.Node.EventType.POSITION_CHANGED, this.onPositionChanged, this);
}
protected removeEventListener() {
this.node.off(cc.Node.EventType.POSITION_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 && this.header.setPosition(new cc.Vec3(x, y));
}
if (start) {
if (this.vertical) {
let x = this.getStartX(this.header);
this.header && this.header.setPosition(new cc.Vec3(x, this.header.position.y));
} else {
let y = this.getStartY(this.header);
this.header && this.header.setPosition(new cc.Vec3(this.header.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: cc.Node | null): number {
if (!trans) return 0;
const size = (trans as any)["__runtime_size"];
const width = size ? size.width : trans.width;
return width * this.getUsedScaleValue(trans.scaleX);
}
protected getScaleHeight(trans: cc.Node | null): number {
if (!trans) return 0;
const size = (trans as any)["__runtime_size"];
const height = size ? size.height : trans.height;
return height * this.getUsedScaleValue(trans.scaleY);
}
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) {
var headerHeight = this.header && this.header.height || 0;
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (force || this.headerBoundary - this.paddingTop > this.viewHeaderBoundary + headerHeight) {
this.pushToFooterHandler();
}
} else {
if (force || this.footerBoundary - this.paddingTop > this.viewHeaderBoundary + headerHeight) {
this.pushToHeaderHandler();
}
}
} else {
var headerWidth = this.header && this.header.width || 0;
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (force || this.headerBoundary + this.paddingLeft < this.viewHeaderBoundary - headerWidth) {
this.pushToFooterHandler();
}
} else {
if (force || this.footerBoundary + this.paddingLeft < this.viewHeaderBoundary - headerWidth) {
this.pushToHeaderHandler();
}
}
}
}
/** 向头部填充 force如果为true 则强制填充 */
protected pushToHeader(force: boolean = false) {
if (this.vertical) {
var footerHeight = this.footer && this.footer.height || 0;
if (this.verticalAxisDirection == VerticalAxisDirection.TOP_TO_BOTTOM) {
if (force || this.footerBoundary + this.paddingBottom < this.viewFooterBoundary - footerHeight) {
this.pushToHeaderHandler();
}
} else {
if (force || this.headerBoundary + this.paddingBottom < this.viewFooterBoundary - footerHeight) {
this.pushToFooterHandler();
}
}
} else {
var footerWidth = this.footer && this.footer.width || 0;
if (this.horizontalAxisDirection == HorizontalAxisDirection.LEFT_TO_RIGHT) {
if (force || this.footerBoundary - this.paddingRight > this.viewFooterBoundary + footerWidth) {
this.pushToHeaderHandler();
}
} else {
if (force || this.headerBoundary - this.paddingRight > this.viewFooterBoundary + footerWidth) {
this.pushToFooterHandler();
}
}
}
}
protected pushToFooterHandler() {
var node: any = this.header;
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.setSiblingIndex(this.node.children.length);
}
protected pushToHeaderHandler() {
var node: any = this.footer;
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.setSiblingIndex(0);
}
/** 通知给定的node刷新数据 */
protected notifyRefreshItem(target: Node) {
cc.Component.EventHandler.emitEvents(this.refreshItemEvents, target, (target as any)['__index']);
}
//
public OnTouchEvent(): void {
this.scrollView.node.on(cc.Node.EventType.TOUCH_START, this.scrollView._onTouchBegan, this.scrollView, true);
this.scrollView.node.on(cc.Node.EventType.TOUCH_MOVE, this.scrollView._onTouchMoved, this.scrollView, true);
this.scrollView.node.on(cc.Node.EventType.TOUCH_END, this.scrollView._onTouchEnded, this.scrollView, true);
this.scrollView.node.on(cc.Node.EventType.TOUCH_CANCEL, this.scrollView._onTouchCancelled, this.scrollView, true);
}
public OffTouchEvent(): void {
this.scrollView.node.off(cc.Node.EventType.TOUCH_START, this.scrollView._onTouchBegan, this.scrollView, true);
this.scrollView.node.off(cc.Node.EventType.TOUCH_MOVE, this.scrollView._onTouchMoved, this.scrollView, true);
this.scrollView.node.off(cc.Node.EventType.TOUCH_END, this.scrollView._onTouchEnded, this.scrollView, true);
this.scrollView.node.off(cc.Node.EventType.TOUCH_CANCEL, this.scrollView._onTouchCancelled, this.scrollView, true);
}
}