@cc-component/cc-ex-component 1.1.6 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/core/BaseReference.ts +40 -0
- package/assets/{video/VideoComponent.ts.meta → core/BaseReference.ts.meta} +1 -1
- package/assets/core/BaseViewModelData.ts +12 -0
- package/assets/{video/Interface.ts.meta → core/BaseViewModelData.ts.meta} +1 -1
- package/assets/core/ReferenceComponent.ts +317 -0
- package/assets/core/ViewModel.ts +542 -0
- package/assets/{video/IVideo.ts.meta → core/ViewModel.ts.meta} +9 -9
- package/assets/ex/EXButton.ts +191 -0
- package/assets/ex/EXButton.ts.meta +9 -0
- package/assets/ex/ExCommon.ts +6 -4
- package/assets/ex/ExTool.ts +116 -0
- package/assets/ex/ExTool.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/custom-grid-flow-layout.ts +105 -0
- package/assets/lib/collectView/lib-ext/custom-grid-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/horizontal-center-layout.ts +84 -0
- package/assets/lib/collectView/lib-ext/horizontal-center-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-card-page-layout.ts +132 -0
- package/assets/lib/collectView/lib-ext/yx-card-page-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-carousel-layout.ts +156 -0
- package/assets/lib/collectView/lib-ext/yx-carousel-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-cover-layout.ts +405 -0
- package/assets/lib/collectView/lib-ext/yx-cover-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-masonry-flow-layout.ts +194 -0
- package/assets/lib/collectView/lib-ext/yx-masonry-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-page-view.ts +232 -0
- package/assets/lib/collectView/lib-ext/yx-page-view.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext/yx-table-view.ts +159 -0
- package/assets/lib/collectView/lib-ext/yx-table-view.ts.meta +9 -0
- package/assets/lib/collectView/lib-ext.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-collection-view.ts +1549 -0
- package/assets/lib/collectView/lib_collect/yx-collection-view.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-compact-flow-layout.ts +364 -0
- package/assets/lib/collectView/lib_collect/yx-compact-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-flow-layout.ts +909 -0
- package/assets/lib/collectView/lib_collect/yx-flow-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect/yx-table-layout.ts +352 -0
- package/assets/lib/collectView/lib_collect/yx-table-layout.ts.meta +9 -0
- package/assets/lib/collectView/lib_collect.meta +9 -0
- package/assets/{video/list.meta → lib/collectView.meta} +9 -9
- package/assets/lib/tableView/IListView.ts +17 -0
- package/assets/lib/tableView/IListView.ts.meta +9 -0
- package/assets/lib/tableView/ListView.ts +197 -0
- package/assets/lib/tableView/ListView.ts.meta +9 -0
- package/assets/lib/tableView/ListViewPage.ts +1048 -0
- package/assets/lib/tableView/ListViewPage.ts.meta +9 -0
- package/assets/lib/tableView/ListViewPageLoop.ts +922 -0
- package/assets/lib/tableView/ListViewPageLoop.ts.meta +1 -0
- package/assets/lib/tableView/TableView.ts +82 -0
- package/assets/lib/tableView/TableView.ts.meta +9 -0
- package/assets/lib/tableView.meta +9 -0
- package/assets/{video.meta → lib.meta} +1 -1
- package/assets/platform/Interface.ts +15 -10
- package/assets/platform/android/AndroidModule.ts +12 -0
- package/assets/platform/android/AndroidModule.ts.meta +9 -0
- package/assets/platform/android/AndroidSDK.ts +1 -2
- package/assets/platform/base/PlatfprmModule.ts +44 -29
- package/assets/platform/base/SDKBase.ts +2 -2
- package/assets/platform/base/TTSDK.ts +21 -10
- package/assets/platform/base/WXSDK.ts +15 -16
- package/assets/platform/wx/MiniSDK.ts +41 -3
- package/assets/platform/wx/wxmini.d.ts +2 -2
- package/index.ts +10 -3
- package/package.json +1 -1
- package/assets/core/ReferenceCollector.ts +0 -172
- package/assets/video/IVideo.ts +0 -73
- package/assets/video/Interface.ts +0 -25
- package/assets/video/VideoComponent.prefab +0 -614
- package/assets/video/VideoComponent.prefab.meta +0 -13
- package/assets/video/VideoComponent.ts +0 -33
- package/assets/video/VideoManager.ts +0 -399
- package/assets/video/VideoManager.ts.meta +0 -9
- package/assets/video/VideoModule.ts +0 -137
- package/assets/video/VideoModule.ts.meta +0 -9
- package/assets/video/VideoPlayTT.ts +0 -338
- package/assets/video/VideoPlayTT.ts.meta +0 -9
- package/assets/video/VideoPlayWX.ts +0 -274
- package/assets/video/VideoPlayWX.ts.meta +0 -9
- package/assets/video/VideoPlayWeb.ts +0 -228
- package/assets/video/VideoPlayWeb.ts.meta +0 -9
- /package/assets/core/{ReferenceCollector.ts.meta → ReferenceComponent.ts.meta} +0 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
import { log, math, UITransform, warn } from "cc";
|
|
2
|
+
import { YXCollectionView, YXIndexPath, YXLayout, YXLayoutAttributes } from "./yx-collection-view";
|
|
3
|
+
|
|
4
|
+
enum _yx_table_layout_supplementary_kinds {
|
|
5
|
+
HEADER = 'header',
|
|
6
|
+
FOOTER = 'footer',
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export class YXTableLayout extends YXLayout {
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* 行高
|
|
13
|
+
*/
|
|
14
|
+
rowHeight: number | ((indexPath: YXIndexPath) => number) = 100
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 内容上边距
|
|
18
|
+
*/
|
|
19
|
+
top: number = 0
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 内容下边距
|
|
23
|
+
*/
|
|
24
|
+
bottom: number = 0
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* 节点之间间距
|
|
28
|
+
*/
|
|
29
|
+
spacing: number = 0
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* 区头高度
|
|
33
|
+
*/
|
|
34
|
+
sectionHeaderHeight: number | ((section: number) => number) = null
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* 区尾高度
|
|
38
|
+
*/
|
|
39
|
+
sectionFooterHeight: number | ((section: number) => number) = null
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 钉住 header 的位置 ( header 吸附在列表可见范围内 )
|
|
43
|
+
*/
|
|
44
|
+
sectionHeadersPinToVisibleBounds: boolean = false
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* 钉住 footer 的位置 ( footer 吸附在列表可见范围内 )
|
|
48
|
+
*/
|
|
49
|
+
sectionFootersPinToVisibleBounds: boolean = false
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* 区头/区尾标识
|
|
53
|
+
*/
|
|
54
|
+
static SupplementaryKinds = _yx_table_layout_supplementary_kinds
|
|
55
|
+
|
|
56
|
+
protected originalHeaderRect: Map<number, math.Rect> = new Map() // 保存所有 header 的原始位置
|
|
57
|
+
protected originalFooterRect: Map<number, math.Rect> = new Map() // 保存所有 footer 的原始位置
|
|
58
|
+
|
|
59
|
+
// 为了优化查找,额外维护几个数组按类别管理所有的布局属性,空间换时间
|
|
60
|
+
protected allCellAttributes: YXLayoutAttributes[] = []
|
|
61
|
+
protected allHeaderAttributes: YXLayoutAttributes[] = []
|
|
62
|
+
protected allFooterAttributes: YXLayoutAttributes[] = []
|
|
63
|
+
|
|
64
|
+
prepare(collectionView: YXCollectionView): void {
|
|
65
|
+
// 设置列表的滚动方向(这套布局固定为垂直方向滚动)
|
|
66
|
+
collectionView.scrollView.horizontal = false
|
|
67
|
+
collectionView.scrollView.vertical = true
|
|
68
|
+
if (collectionView.scrollDirection === YXCollectionView.ScrollDirection.HORIZONTAL) {
|
|
69
|
+
// 由于这套布局规则只支持垂直方向布局,当外部配置了水平方向滚动时这里可以给个警告
|
|
70
|
+
warn(`YXTableLayout 仅支持垂直方向排列`)
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// 清空一下布局属性数组
|
|
74
|
+
this.attributes = []
|
|
75
|
+
this.allCellAttributes = []
|
|
76
|
+
this.allHeaderAttributes = []
|
|
77
|
+
this.allFooterAttributes = []
|
|
78
|
+
this.originalHeaderRect.clear()
|
|
79
|
+
this.originalFooterRect.clear()
|
|
80
|
+
|
|
81
|
+
// 获取列表宽度
|
|
82
|
+
const contentWidth = collectionView.node.getComponent(UITransform).width
|
|
83
|
+
|
|
84
|
+
// 声明一个临时变量,用来记录当前所有内容的总高度
|
|
85
|
+
let contentHeight = 0
|
|
86
|
+
|
|
87
|
+
// 获取列表一共分多少个区
|
|
88
|
+
let numberOfSections = collectionView.getNumberOfSections()
|
|
89
|
+
|
|
90
|
+
// 为每条数据对应的生成一个布局属性
|
|
91
|
+
for (let section = 0; section < numberOfSections; section++) {
|
|
92
|
+
|
|
93
|
+
// 创建一个区索引
|
|
94
|
+
let sectionIndexPath = new YXIndexPath(section, 0)
|
|
95
|
+
|
|
96
|
+
// 通过区索引创建一个区头节点布局属性
|
|
97
|
+
let sectionHeaderHeight = 0
|
|
98
|
+
if (this.sectionHeaderHeight) {
|
|
99
|
+
sectionHeaderHeight = this.sectionHeaderHeight instanceof Function ? this.sectionHeaderHeight(section) : this.sectionHeaderHeight
|
|
100
|
+
}
|
|
101
|
+
if (sectionHeaderHeight > 0) {
|
|
102
|
+
let headerAttr = YXLayoutAttributes.layoutAttributesForSupplementary(sectionIndexPath, YXTableLayout.SupplementaryKinds.HEADER)
|
|
103
|
+
|
|
104
|
+
// 确定这个节点的位置
|
|
105
|
+
headerAttr.frame.x = 0
|
|
106
|
+
headerAttr.frame.width = contentWidth
|
|
107
|
+
headerAttr.frame.height = sectionHeaderHeight
|
|
108
|
+
headerAttr.frame.y = contentHeight
|
|
109
|
+
|
|
110
|
+
// 调整层级
|
|
111
|
+
headerAttr.zIndex = 1
|
|
112
|
+
|
|
113
|
+
// 重要: 保存布局属性
|
|
114
|
+
this.attributes.push(headerAttr)
|
|
115
|
+
this.originalHeaderRect.set(section, headerAttr.frame.clone())
|
|
116
|
+
this.allHeaderAttributes.push(headerAttr)
|
|
117
|
+
|
|
118
|
+
// 更新整体内容高度
|
|
119
|
+
contentHeight = headerAttr.frame.yMax
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 将 top 配置应用到每个区
|
|
123
|
+
contentHeight = contentHeight + this.top
|
|
124
|
+
|
|
125
|
+
// 获取这个区内的内容数量,注意这里传入的是 section
|
|
126
|
+
let numberOfItems = collectionView.getNumberOfItems(section)
|
|
127
|
+
|
|
128
|
+
for (let item = 0; item < numberOfItems; item++) {
|
|
129
|
+
|
|
130
|
+
// 创建索引,注意这里的 section 已经改为正确的 section 了
|
|
131
|
+
let indexPath = new YXIndexPath(section, item)
|
|
132
|
+
|
|
133
|
+
// 通过索引创建一个 cell 节点的布局属性
|
|
134
|
+
let attr = YXLayoutAttributes.layoutAttributesForCell(indexPath)
|
|
135
|
+
|
|
136
|
+
// 通过索引获取这个节点的高度
|
|
137
|
+
let rowHeight = this.rowHeight instanceof Function ? this.rowHeight(indexPath) : this.rowHeight
|
|
138
|
+
|
|
139
|
+
// 确定这个节点的位置
|
|
140
|
+
attr.frame.x = 0
|
|
141
|
+
attr.frame.width = contentWidth
|
|
142
|
+
attr.frame.height = rowHeight
|
|
143
|
+
attr.frame.y = contentHeight + (item > 0 ? this.spacing : 0)
|
|
144
|
+
|
|
145
|
+
// 重要: 保存布局属性
|
|
146
|
+
this.attributes.push(attr)
|
|
147
|
+
this.allCellAttributes.push(attr)
|
|
148
|
+
|
|
149
|
+
// 更新当前内容高度
|
|
150
|
+
contentHeight = attr.frame.yMax
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 高度补一个底部间距,跟 top 一样,也是应用到每个区
|
|
154
|
+
contentHeight = contentHeight + this.bottom
|
|
155
|
+
|
|
156
|
+
// 通过区索引创建一个区尾节点布局属性
|
|
157
|
+
let sectionFooterHeight = 0
|
|
158
|
+
if (this.sectionFooterHeight) {
|
|
159
|
+
sectionFooterHeight = this.sectionFooterHeight instanceof Function ? this.sectionFooterHeight(section) : this.sectionFooterHeight
|
|
160
|
+
}
|
|
161
|
+
if (sectionFooterHeight > 0) {
|
|
162
|
+
let footerAttr = YXLayoutAttributes.layoutAttributesForSupplementary(sectionIndexPath, YXTableLayout.SupplementaryKinds.FOOTER)
|
|
163
|
+
|
|
164
|
+
// 确定这个节点的位置
|
|
165
|
+
footerAttr.frame.x = 0
|
|
166
|
+
footerAttr.frame.width = contentWidth
|
|
167
|
+
footerAttr.frame.height = sectionFooterHeight
|
|
168
|
+
footerAttr.frame.y = contentHeight
|
|
169
|
+
|
|
170
|
+
// 调整层级
|
|
171
|
+
footerAttr.zIndex = 1
|
|
172
|
+
|
|
173
|
+
// 重要: 保存布局属性
|
|
174
|
+
this.attributes.push(footerAttr)
|
|
175
|
+
this.originalFooterRect.set(section, footerAttr.frame.clone())
|
|
176
|
+
this.allFooterAttributes.push(footerAttr)
|
|
177
|
+
|
|
178
|
+
// 更新整体内容高度
|
|
179
|
+
contentHeight = footerAttr.frame.yMax
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 重要: 设置内容区域总大小,只有确定了滚动区域的大小列表才能滚动
|
|
184
|
+
this.contentSize = new math.Size(contentWidth, contentHeight)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
initOffset(collectionView: YXCollectionView): void {
|
|
188
|
+
// 列表首次刷新时,调整一下列表的偏移位置
|
|
189
|
+
collectionView.scrollView.scrollToTop()
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
layoutAttributesForElementsInRect(rect: math.Rect, collectionView: YXCollectionView): YXLayoutAttributes[] {
|
|
193
|
+
let result = this.visibleElementsInRect(rect, collectionView)
|
|
194
|
+
if (this.sectionHeadersPinToVisibleBounds == false && this.sectionFootersPinToVisibleBounds == false) {
|
|
195
|
+
return result // 不需要调整节点位置,直接返回就好
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
let numberOfSections = collectionView.getNumberOfSections()
|
|
199
|
+
let scrollOffset = collectionView.scrollView.getScrollOffset()
|
|
200
|
+
for (let index = 0; index < result.length; index++) {
|
|
201
|
+
const element = result[index];
|
|
202
|
+
if (element.elementCategory === 'Supplementary') {
|
|
203
|
+
|
|
204
|
+
if (this.sectionHeadersPinToVisibleBounds && element.supplementaryKinds === YXTableLayout.SupplementaryKinds.HEADER) {
|
|
205
|
+
const originalFrame = this.originalHeaderRect.get(element.indexPath.section)
|
|
206
|
+
element.frame.y = originalFrame.y
|
|
207
|
+
if (scrollOffset.y > originalFrame.y) {
|
|
208
|
+
element.frame.y = scrollOffset.y
|
|
209
|
+
}
|
|
210
|
+
const nextOriginalFrame = this.getNextOriginalFrame(element.indexPath.section, YXTableLayout.SupplementaryKinds.FOOTER, numberOfSections)
|
|
211
|
+
if (nextOriginalFrame) {
|
|
212
|
+
if (element.frame.yMax > nextOriginalFrame.y) {
|
|
213
|
+
element.frame.y = nextOriginalFrame.y - element.frame.height
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
if (this.sectionFootersPinToVisibleBounds && element.supplementaryKinds === YXTableLayout.SupplementaryKinds.FOOTER) {
|
|
219
|
+
let bottom = scrollOffset.y + collectionView.scrollView.view.height
|
|
220
|
+
const originalFrame = this.originalFooterRect.get(element.indexPath.section)
|
|
221
|
+
const previousOriginalFrame = this.getPreviousOriginalFrame(element.indexPath.section, YXTableLayout.SupplementaryKinds.HEADER)
|
|
222
|
+
element.frame.y = originalFrame.y
|
|
223
|
+
if (bottom < originalFrame.yMax) {
|
|
224
|
+
element.frame.y = bottom - element.frame.height
|
|
225
|
+
if (previousOriginalFrame) {
|
|
226
|
+
if (element.frame.y < previousOriginalFrame.yMax) {
|
|
227
|
+
element.frame.y = previousOriginalFrame.yMax
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
return result
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
shouldUpdateAttributesZIndex(): boolean {
|
|
238
|
+
return this.sectionHeadersPinToVisibleBounds || this.sectionFootersPinToVisibleBounds
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
shouldUpdateAttributesForBoundsChange(): boolean {
|
|
242
|
+
return this.sectionHeadersPinToVisibleBounds || this.sectionFootersPinToVisibleBounds
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* 获取 `section` 下一个 header 或者 footer 的位置
|
|
247
|
+
*/
|
|
248
|
+
protected getNextOriginalFrame(section: number, kinds: _yx_table_layout_supplementary_kinds, total: number) {
|
|
249
|
+
if (section >= total) { return null }
|
|
250
|
+
if (kinds === YXTableLayout.SupplementaryKinds.HEADER) {
|
|
251
|
+
let result = this.originalHeaderRect.get(section)
|
|
252
|
+
if (result) { return result }
|
|
253
|
+
return this.getNextOriginalFrame(section, YXTableLayout.SupplementaryKinds.FOOTER, total)
|
|
254
|
+
}
|
|
255
|
+
if (kinds === YXTableLayout.SupplementaryKinds.FOOTER) {
|
|
256
|
+
let result = this.originalFooterRect.get(section)
|
|
257
|
+
if (result) { return result }
|
|
258
|
+
return this.getNextOriginalFrame(section + 1, YXTableLayout.SupplementaryKinds.HEADER, total)
|
|
259
|
+
}
|
|
260
|
+
return null
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* 获取 `section` 前一个 header 或者 footer 的位置
|
|
265
|
+
*/
|
|
266
|
+
protected getPreviousOriginalFrame(section: number, kinds: _yx_table_layout_supplementary_kinds) {
|
|
267
|
+
if (section < 0) { return null }
|
|
268
|
+
if (kinds === YXTableLayout.SupplementaryKinds.HEADER) {
|
|
269
|
+
let result = this.originalHeaderRect.get(section)
|
|
270
|
+
if (result) { return result }
|
|
271
|
+
return this.getPreviousOriginalFrame(section - 1, YXTableLayout.SupplementaryKinds.FOOTER)
|
|
272
|
+
}
|
|
273
|
+
if (kinds === YXTableLayout.SupplementaryKinds.FOOTER) {
|
|
274
|
+
let result = this.originalFooterRect.get(section)
|
|
275
|
+
if (result) { return result }
|
|
276
|
+
return this.getPreviousOriginalFrame(section, YXTableLayout.SupplementaryKinds.HEADER)
|
|
277
|
+
}
|
|
278
|
+
return null
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* 抽出来一个方法用来优化列表性能
|
|
283
|
+
* 在优化之前,可以先看一下 @see YXLayout.layoutAttributesForElementsInRect 关于返回值的说明
|
|
284
|
+
* 对于有序列表来说,一般都是可以通过二分查找来进行优化
|
|
285
|
+
*/
|
|
286
|
+
protected visibleElementsInRect(rect: math.Rect, collectionView: YXCollectionView) {
|
|
287
|
+
if (this.attributes.length <= 100) { return this.attributes } // 少量数据就不查了,直接返回全部
|
|
288
|
+
|
|
289
|
+
let result: YXLayoutAttributes[] = []
|
|
290
|
+
|
|
291
|
+
// header 跟 footer 暂时不考虑,数据相对来说不算很多,直接全部返回
|
|
292
|
+
result.push(...this.allHeaderAttributes)
|
|
293
|
+
result.push(...this.allFooterAttributes)
|
|
294
|
+
|
|
295
|
+
// 关于 cell,这里用二分查找来优化一下
|
|
296
|
+
// 首先通过二分先查出个大概位置
|
|
297
|
+
let midIdx = -1
|
|
298
|
+
let left = 0
|
|
299
|
+
let right = this.allCellAttributes.length - 1
|
|
300
|
+
|
|
301
|
+
while (left <= right && right >= 0) {
|
|
302
|
+
let mid = left + (right - left) / 2
|
|
303
|
+
mid = Math.floor(mid)
|
|
304
|
+
let attr = this.allCellAttributes[mid]
|
|
305
|
+
if (rect.intersects(attr.frame)) {
|
|
306
|
+
midIdx = mid
|
|
307
|
+
break
|
|
308
|
+
}
|
|
309
|
+
if (rect.yMax < attr.frame.yMin || rect.xMax < attr.frame.xMin) {
|
|
310
|
+
right = mid - 1
|
|
311
|
+
} else {
|
|
312
|
+
left = mid + 1
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// 二分查找出错了,返回全部的布局属性
|
|
317
|
+
if (midIdx < 0) {
|
|
318
|
+
return this.attributes
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// 把模糊查到这个先加进来
|
|
322
|
+
result.push(this.allCellAttributes[midIdx])
|
|
323
|
+
|
|
324
|
+
// 然后依次往前检查,直到超出当前的显示范围
|
|
325
|
+
let startIdx = midIdx
|
|
326
|
+
while (startIdx > 0) {
|
|
327
|
+
let idx = startIdx - 1
|
|
328
|
+
let attr = this.allCellAttributes[idx]
|
|
329
|
+
if (rect.intersects(attr.frame) == false) {
|
|
330
|
+
break
|
|
331
|
+
}
|
|
332
|
+
result.push(attr)
|
|
333
|
+
startIdx = idx
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// 依次往后检查,直到超出当前的显示范围
|
|
337
|
+
let endIdx = midIdx
|
|
338
|
+
while (endIdx < this.allCellAttributes.length - 1) {
|
|
339
|
+
let idx = endIdx + 1
|
|
340
|
+
let attr = this.allCellAttributes[idx]
|
|
341
|
+
if (rect.intersects(attr.frame) == false) {
|
|
342
|
+
break
|
|
343
|
+
}
|
|
344
|
+
result.push(attr)
|
|
345
|
+
endIdx = idx
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return result
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"ver": "1.2.0",
|
|
3
|
-
"importer": "directory",
|
|
4
|
-
"imported": true,
|
|
5
|
-
"uuid": "
|
|
6
|
-
"files": [],
|
|
7
|
-
"subMetas": {},
|
|
8
|
-
"userData": {}
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"ver": "1.2.0",
|
|
3
|
+
"importer": "directory",
|
|
4
|
+
"imported": true,
|
|
5
|
+
"uuid": "3e16331d-321f-4cff-86f3-d1740e9f5915",
|
|
6
|
+
"files": [],
|
|
7
|
+
"subMetas": {},
|
|
8
|
+
"userData": {}
|
|
9
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Size, Node } from "cc";
|
|
2
|
+
import { ListView } from "./ListView";
|
|
3
|
+
|
|
4
|
+
export interface IIndexPath {
|
|
5
|
+
row: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ILayout {
|
|
8
|
+
horizontalSpacing: number;
|
|
9
|
+
verticalSpacing: number;
|
|
10
|
+
}
|
|
11
|
+
export interface IListView {
|
|
12
|
+
cellForItemAt(indexPath: IIndexPath, collectionView: ListView): Node;
|
|
13
|
+
numberOfItems(): number;
|
|
14
|
+
onTouchCellAt(indexPath: IIndexPath);
|
|
15
|
+
itemSize(): Size;
|
|
16
|
+
moveFinish?(indexPath: IIndexPath);
|
|
17
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { _decorator, Component, Enum, NodePool, Prefab, ScrollView, Size, UITransform, utils, v2, v3 } from 'cc';
|
|
2
|
+
import { IIndexPath, ILayout, IListView } from './IListView';
|
|
3
|
+
import { Sprite } from 'cc';
|
|
4
|
+
import { Color } from 'cc';
|
|
5
|
+
import { Vec2 } from 'cc';
|
|
6
|
+
import { EventTouch } from 'cc';
|
|
7
|
+
import { Vec3 } from 'cc';
|
|
8
|
+
import { Node } from 'cc';
|
|
9
|
+
import { Layers, Widget } from 'cc';
|
|
10
|
+
const { ccclass, property } = _decorator;
|
|
11
|
+
|
|
12
|
+
@ccclass(`register_element_info`)
|
|
13
|
+
export class register_element_info {
|
|
14
|
+
@property({ type: Prefab, tooltip: `cell 节点预制体,必须配置` })
|
|
15
|
+
prefab: Prefab = null
|
|
16
|
+
@property({ tooltip: `节点重用标识符,必须配置` })
|
|
17
|
+
identifier: string = ``
|
|
18
|
+
// @property({ tooltip: `节点挂载的自定义组件\n如果需要监听 NodePool 的重用/回收事件,确保你的自定义组件已经实现了 YXCollectionViewCell 接口并配置此属性为你的自定义组件名\n如果不需要,可以忽略此配置` })
|
|
19
|
+
// comp: string = ``
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
export class node_element_comp extends Component {
|
|
24
|
+
/**
|
|
25
|
+
* 此节点是通过哪个标识符创建的
|
|
26
|
+
*/
|
|
27
|
+
identifier: string
|
|
28
|
+
node: Node;
|
|
29
|
+
row: number;
|
|
30
|
+
col: number;
|
|
31
|
+
row_data: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* 定义列表的滚动方向
|
|
36
|
+
*/
|
|
37
|
+
export enum collection_view_scroll_direction {
|
|
38
|
+
/**
|
|
39
|
+
* 水平滚动
|
|
40
|
+
*/
|
|
41
|
+
HORIZONTAL,
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 垂直滚动
|
|
45
|
+
*/
|
|
46
|
+
VERTICAL,
|
|
47
|
+
}
|
|
48
|
+
Enum(collection_view_scroll_direction)
|
|
49
|
+
export enum DirectionScroll {
|
|
50
|
+
UP,
|
|
51
|
+
DOWN,
|
|
52
|
+
NONE,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
@ccclass('scroll_config')
|
|
57
|
+
export class scroll_config {
|
|
58
|
+
@property({ type: Node, tooltip: `content` })
|
|
59
|
+
content: Node = null;
|
|
60
|
+
@property({ type: collection_view_scroll_direction, tooltip: `列表滚动方向` })
|
|
61
|
+
scrollDirection: collection_view_scroll_direction = collection_view_scroll_direction.HORIZONTAL
|
|
62
|
+
@property({ type: [register_element_info], visible: true, displayName: `Register Cells`, tooltip: `配置此列表内需要用到的 cell 节点类型` })
|
|
63
|
+
registerCell: register_element_info[] = []
|
|
64
|
+
@property({ displayName: `最大显示cell数量` })
|
|
65
|
+
maxShowCount = 7;
|
|
66
|
+
@property({ displayName: `中间大两边小` })
|
|
67
|
+
isScale: boolean = false;
|
|
68
|
+
@property({ displayName: `循环滚动>>>>` })
|
|
69
|
+
isLoop: boolean = false;
|
|
70
|
+
@property({ displayName: `cell间隔` })
|
|
71
|
+
cellSpace: number = 20
|
|
72
|
+
@property({
|
|
73
|
+
visible() {
|
|
74
|
+
return !this.isLoop
|
|
75
|
+
}, displayName: `cell间隔左`
|
|
76
|
+
})
|
|
77
|
+
cellSpaceLeft: number = 20
|
|
78
|
+
@property({
|
|
79
|
+
visible() {
|
|
80
|
+
return !this.isLoop
|
|
81
|
+
}, displayName: `cell间隔右`
|
|
82
|
+
})
|
|
83
|
+
cellSpaceRight: number = 20
|
|
84
|
+
|
|
85
|
+
@property({ displayName: `整页滚动>>>>` })
|
|
86
|
+
isPage: boolean = false
|
|
87
|
+
|
|
88
|
+
@property({
|
|
89
|
+
visible() {
|
|
90
|
+
return this.isPage
|
|
91
|
+
}, displayName: `轻扫时间`
|
|
92
|
+
})
|
|
93
|
+
swipeTime = 0.5;
|
|
94
|
+
@property({
|
|
95
|
+
visible() {
|
|
96
|
+
return this.isPage || this.isCenter
|
|
97
|
+
}, displayName: `居中动画时间`
|
|
98
|
+
})
|
|
99
|
+
pageTime = 0.4
|
|
100
|
+
@property({
|
|
101
|
+
visible() {
|
|
102
|
+
return !this.isLoop
|
|
103
|
+
}, displayName: `停止后cell居中`
|
|
104
|
+
})
|
|
105
|
+
isCenter: boolean = false
|
|
106
|
+
}
|
|
107
|
+
@ccclass('ListView')
|
|
108
|
+
export class ListView extends ScrollView {
|
|
109
|
+
@property({ serializable: true, type: scroll_config, visible: true, displayName: `配置滚动` })
|
|
110
|
+
config: scroll_config = new scroll_config();
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
public delegate: IListView
|
|
114
|
+
protected contentUT: UITransform;
|
|
115
|
+
public nodeUT: UITransform;
|
|
116
|
+
protected cellPool: Map<string, NodePool> = new Map()
|
|
117
|
+
protected cellListAll: Node[] = []
|
|
118
|
+
protected visbleCellList: node_element_comp[] = []
|
|
119
|
+
numberOfItems = 0;
|
|
120
|
+
itemSize = new Size();
|
|
121
|
+
|
|
122
|
+
scrollDir: number;
|
|
123
|
+
isReload: boolean = false;
|
|
124
|
+
lastOffset: Vec2;
|
|
125
|
+
isRighthHua = false;
|
|
126
|
+
isScroll = true;
|
|
127
|
+
public init() {
|
|
128
|
+
this.elastic = false
|
|
129
|
+
this.bounceDuration = 0
|
|
130
|
+
}
|
|
131
|
+
public reloadData() {
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
public moveToRow(index: number, time = 0.2) {
|
|
135
|
+
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//子类重写
|
|
139
|
+
dequeueReusableCell(identifier: string, indexPath: IIndexPath): Node {
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
putNode(cell: Node) {
|
|
144
|
+
const view = cell.getComponent(node_element_comp)
|
|
145
|
+
this.cellPool.get(view.identifier).put(cell)
|
|
146
|
+
//console.log(this.cellPool.get(view.identifier))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
inBox(box1: UITransform, box2: UITransform, inBox: boolean): boolean {
|
|
151
|
+
// 获取 box 和 box2 的边界框
|
|
152
|
+
const rect1 = this.getBoxRect(box1)
|
|
153
|
+
const rect2 = this.getBoxRect(box2)
|
|
154
|
+
// 检查 box 的四个边是否都在 box2 的边界框内
|
|
155
|
+
let isInside = false;
|
|
156
|
+
if (inBox) {
|
|
157
|
+
isInside =
|
|
158
|
+
rect1.minX <= rect2.minX && // box 左边界在 box2 左边界右侧
|
|
159
|
+
rect1.maxX >= rect2.maxX && // box 右边界在 box2 右边界左侧
|
|
160
|
+
rect1.minY <= rect2.minY && // box 下边界在 box2 下边界上侧
|
|
161
|
+
rect1.maxY >= rect2.maxY; // box 上边界在 box2 上边界下侧
|
|
162
|
+
} else {
|
|
163
|
+
isInside =
|
|
164
|
+
rect1.minX > rect2.maxX ||
|
|
165
|
+
rect1.maxX < rect2.minX || // box 右边界在 box2 右边界左侧
|
|
166
|
+
rect1.minY > rect2.maxY || // box 下边界在 box2 下边界上侧
|
|
167
|
+
rect1.maxY < rect2.minY; // box 上边界在 box2 上边界下侧
|
|
168
|
+
}
|
|
169
|
+
return isInside;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
getBoxRect(box: UITransform) {
|
|
173
|
+
const min_x = box.node.worldPosition.x - box.width * 0.5
|
|
174
|
+
const max_x = box.node.worldPosition.x + box.width * 0.5
|
|
175
|
+
const minY = box.node.worldPosition.y - box.height * 0.5
|
|
176
|
+
const maxY = box.node.worldPosition.y + box.height * 0.5
|
|
177
|
+
return { minX: min_x, maxX: max_x, minY: minY, maxY: maxY }
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
public CreateNnode(name: string, isWidget: boolean = true) {
|
|
182
|
+
const node = new Node(name);
|
|
183
|
+
node.addComponent(UITransform)
|
|
184
|
+
node.layer = Layers.Enum.UI_2D;
|
|
185
|
+
if (isWidget) {
|
|
186
|
+
const w: Widget = node.addComponent(Widget);
|
|
187
|
+
w.isAlignLeft = w.isAlignRight = w.isAlignTop = w.isAlignBottom = true;
|
|
188
|
+
w.left = w.right = w.top = w.bottom = 0;
|
|
189
|
+
w.alignMode = 2;
|
|
190
|
+
w.enabled = true;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return node;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
}
|