1# WaterFlow
2
3
4瀑布流容器,由“行”和“列”分割的单元格所组成,通过容器自身的排列规则,将不同大小的“项目”自上而下,如瀑布般紧密布局。
5
6
7> **说明:**
8>
9> 该组件从API Version 9 开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
10
11
12## 子组件
13
14
15仅支持[FlowItem](ts-container-flowitem.md)子组件,支持渲染控制类型([if/else](../../../quick-start/arkts-rendering-control-ifelse.md)、[ForEach](../../../quick-start/arkts-rendering-control-foreach.md)、[LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md)和[Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md))。
16
17>  **说明:**
18>
19>  WaterFlow子组件的visibility属性设置为None时不显示,但该子组件周围的columnsGap、rowsGap、margin仍会生效。
20
21## 接口
22
23WaterFlow(options?:  WaterFlowOptions)
24
25**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
26
27**系统能力:** SystemCapability.ArkUI.ArkUI.Full
28
29**参数:**
30
31| 参数名 | 类型 | 必填 | 说明 |
32| -------- | -------- | -------- | -------- |
33| options |  [WaterFlowOptions](#waterflowoptions对象说明)| 否 | 瀑布流组件参数。 |
34
35
36## WaterFlowOptions对象说明
37
38**系统能力:** SystemCapability.ArkUI.ArkUI.Full
39
40| 名称     | 类型                                        | 必填 | 说明                                     |
41| ---------- | ----------------------------------------------- | ------ | -------------------------------------------- |
42| footer |  [CustomBuilder](ts-types.md#custombuilder8) | 否   | 设置WaterFlow尾部组件。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 |
43| scroller | [Scroller](ts-container-scroll.md#scroller) | 否   | 可滚动组件的控制器,与可滚动组件绑定。<br/>**说明:** <br/>不允许和其他滚动类组件,如:[List](ts-container-list.md)、[Grid](ts-container-grid.md)、[Scroll](ts-container-scroll.md)等绑定同一个滚动控制对象。<br/>**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。 |
44| sections<sup>12+</sup> |  [WaterFlowSections](#waterflowsections12) | 否   | 设置FlowItem分组,实现同一个瀑布流组件内部各分组使用不同列数混合布局。<br/>**说明:** <br/>1. 使用分组混合布局时会忽略columnsTemplate和rowsTemplate属性。<br/>2. 使用分组混合布局时不支持单独设置footer,可以使用最后一个分组作为尾部组件。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。  |
45| layoutMode<sup>12+</sup> |[WaterFlowLayoutMode](#waterflowlayoutmode12枚举说明) | 否 | 设置WaterFlow的布局模式,根据使用场景选择更切合的模式。<br/>**说明:** <br/>默认值:[ALWAYS_TOP_DOWN](#waterflowlayoutmode12枚举说明)。<br/>**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
46
47
48## WaterFlowSections<sup>12+</sup>
49
50瀑布流分组信息。
51
52> **说明:**
53>
54> 使用splice、push、update修改分组信息后需要保证所有分组子节点总数与瀑布流实际子节点总数一致,否则会出现瀑布流因为不能正常布局而无法滑动的问题。
55
56### constructor
57
58constructor()
59
60创建一个瀑布流分组。
61
62**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
63
64**系统能力:** SystemCapability.ArkUI.ArkUI.Full
65
66### splice<sup>12+</sup>
67
68splice(start: number, deleteCount?: number, sections?: Array\<SectionOptions\>): boolean
69
70移除或者替换已存在的分组和/或添加新分组。
71
72**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
73
74**系统能力:** SystemCapability.ArkUI.ArkUI.Full
75
76**参数:**
77
78| 参数名   | 类型                            | 必填   | 说明                   |
79| ---- | ----------------------------- | ---- | -------------------- |
80| start | number | 是    | 从0开始计算的索引,会转换为整数,表示要开始改变分组的位置。<br/>**说明:** <br/>1. 如果索引是负数,则从末尾开始计算,使用`start + WaterFlowSections.length()`。<br/>2. 如果 `start < -WaterFlowSections.length()`,则使用0。<br/>3. 如果 `start >= WaterFlowSections.length()`,则在最后添加新分组。 |
81| deleteCount | number | 否    | 表示要从start开始删除的分组数量。<br/>**说明:** <br/>1. 如果省略了deleteCount,或者其值大于或等于由start指定的位置到WaterFlowSections末尾的分组数量,那么从start到WaterFlowSections末尾的所有分组将被删除。<br/>2. 如果deleteCount是0或者负数,则不会删除任何分组。 |
82| sections | Array<[SectionOptions](#sectionoptions12对象说明)> | 否    | 表示要从start开始加入的分组。如果不指定,`splice()`将只从瀑布流中删除分组。 |
83
84**返回值:**
85
86| 类型                                                         | 说明                                                         |
87| ------------------------------------------------------------ | ------------------------------------------------------------ |
88| boolean | 分组是否修改成功,要加入的分组中有任意分组的itemsCount不是正整数时返回false。 |
89
90
91### push<sup>12+</sup>
92
93push(section: SectionOptions): boolean
94
95将指定分组添加到瀑布流末尾。
96
97**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
98
99**系统能力:** SystemCapability.ArkUI.ArkUI.Full
100
101**参数:**
102
103| 参数名   | 类型                            | 必填   | 说明                   |
104| ---- | ----------------------------- | ---- | -------------------- |
105| section | [SectionOptions](#sectionoptions12对象说明) | 是    | 添加到瀑布流末尾的分组。 |
106
107**返回值:**
108
109| 类型                                                         | 说明                                                         |
110| ------------------------------------------------------------ | ------------------------------------------------------------ |
111| boolean | 分组是否添加成功,新分组的itemsCount不是正整数时返回false。 |
112
113### update<sup>12+</sup>
114
115update(sectionIndex: number, section: SectionOptions): boolean
116
117修改指定索引分组的配置信息。
118
119**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
120
121**系统能力:** SystemCapability.ArkUI.ArkUI.Full
122
123**参数:**
124
125| 参数名   | 类型                            | 必填   | 说明                   |
126| ---- | ----------------------------- | ---- | -------------------- |
127| sectionIndex | number | 是    | 从0开始计算的索引,会转换为整数,表示要修改的分组的位置。<br/>**说明:** <br/>1. 如果索引是负数,则从末尾开始计算,使用`sectionIndex + WaterFlowSections.length()`。<br/>2. 如果`sectionIndex < -WaterFlowSections.length()`,则使用0。<br/>3. 如果`sectionIndex >= WaterFlowSections.length()`,则在最后添加新分组。 |
128| section | [SectionOptions](#sectionoptions12对象说明) | 是    | 新的分组信息。 |
129
130**返回值:**
131
132| 类型                                                         | 说明                                                         |
133| ------------------------------------------------------------ | ------------------------------------------------------------ |
134| boolean | 分组是否更新成功,新分组的itemsCount不是正整数时返回false。 |
135
136### values<sup>12+</sup>
137
138values(): Array\<SectionOptions\>
139
140获取瀑布流中所有分组配置信息。
141
142**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
143
144**系统能力:** SystemCapability.ArkUI.ArkUI.Full
145
146**返回值:**
147
148| 类型                                                         | 说明                                                         |
149| ------------------------------------------------------------ | ------------------------------------------------------------ |
150| Array<[SectionOptions](#sectionoptions12对象说明)> | 瀑布流中所有分组配置信息。 |
151
152### length<sup>12+</sup>
153
154length(): number
155
156获取瀑布流中分组数量。
157
158**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
159
160**系统能力:** SystemCapability.ArkUI.ArkUI.Full
161
162**返回值:**
163
164| 类型                                                         | 说明                                                         |
165| ------------------------------------------------------------ | ------------------------------------------------------------ |
166| number | 瀑布流中分组数量。 |
167
168## SectionOptions<sup>12+</sup>对象说明
169
170FlowItem分组配置信息。
171
172**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
173
174**系统能力:** SystemCapability.ArkUI.ArkUI.Full
175
176| 名称 | 类型 | 必填 | 说明 |
177|------|-----|-----|-----|
178| itemsCount | number | 是 | 分组中FlowItem数量,必须是正整数。若splice、push、update方法收到的分组中有分组的itemsCount小于0,则不会执行该方法。 |
179| crossCount | number | 否 | 纵向布局时为列数,横向布局时为行数,默认值:1。小于1的按默认值处理。 |
180| columnsGap | [Dimension](ts-types.md#dimension10) | 否 | 该分组的列间距,不设置时使用瀑布流的columnsGap,设置非法值时使用0vp。 |
181| rowsGap | [Dimension](ts-types.md#dimension10) | 否 | 该分组的行间距,不设置时使用瀑布流的rowsGap,设置非法值时使用0vp。 |
182| margin | [Margin](ts-types.md#margin) \| [Dimension](ts-types.md#dimension10) | 否 | 该分组的外边距参数为Length类型时,四个方向外边距同时生效。<br>默认值:0<br>单位:vp<br>margin设置百分比时,上下左右外边距均以瀑布流的width作为基础值。 |
183| onGetItemMainSizeByIndex | [GetItemMainSizeByIndex](#getitemmainsizebyindex12) | 否 | 瀑布流组件布局过程中获取指定index的FlowItem的主轴大小,纵向瀑布流时为高度,横向瀑布流时为宽度,单位vp。<br/>**说明:** <br/>1. 同时使用onGetItemMainSizeByIndex和FlowItem的宽高属性时,主轴大小以onGetItemMainSizeByIndex返回结果为准,onGetItemMainSizeByIndex会覆盖FlowItem的主轴长度。<br/>2. 使用onGetItemMainSizeByIndex可以提高瀑布流跳转到指定位置或index时的效率,避免混用设置onGetItemMainSizeByIndex和未设置的分组,会导致布局异常。<br/>3. onGetItemMainSizeByIndex返回负数时FlowItem高度为0。 |
184
185
186## GetItemMainSizeByIndex<sup>12+</sup>
187
188type GetItemMainSizeByIndex = (index: number) => number
189
190根据index获取指定Item的主轴大小。
191
192**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
193
194**系统能力:** SystemCapability.ArkUI.ArkUI.Full
195
196**参数:**
197
198| 参数名   | 类型                            | 必填   | 说明                   |
199| ---- | ----------------------------- | ---- | -------------------- |
200| index | number | 是    | FlowItem在WaterFlow中的索引。 |
201
202**返回值:**
203
204| 类型                                                         | 说明                                                         |
205| ------------------------------------------------------------ | ------------------------------------------------------------ |
206| number | 指定index的FlowItem的主轴大小,纵向瀑布流时为高度,横向瀑布流时为宽度,单位vp。 |
207
208## WaterFlowLayoutMode<sup>12+</sup>枚举说明
209
210**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
211
212**系统能力:** SystemCapability.ArkUI.ArkUI.Full
213
214| 名称 | 值 | 说明 |
215| ------ | ------ | -------------------- |
216| ALWAYS_TOP_DOWN | 0 | 默认的从上到下的布局模式。视窗内的FlowItem依赖视窗上方所有FlowItem的布局信息。因此跳转或切换列数时,需要计算出上方所有的FlowItem的布局信息。 |
217| SLIDING_WINDOW | 1 | 移动窗口式的布局模式。只考虑视窗内的布局信息,对视窗上方的FlowItem没有依赖关系,因此向后跳转或切换列数时只需要布局视窗内的FlowItem。有频繁切换列数的场景的应用建议使用该模式。 <br/>**说明:** <br/>1. 无动画跳转到较远的位置时,会以目标位置为基准,向前或向后布局FlowItem。这之后如果滑回跳转前的位置,内容的布局效果可能和之前不一致。 这个效果会导致跳转后回滑到顶部时,顶部节点可能不对齐。所以该布局模式下会在滑动到顶部后自动调整布局,保证顶部对齐。在有多个分组的情况下,会在滑动结束时调整在视窗内的分组。<br/> 2. 该模式不支持使用滚动条,就算设置了滚动条也无法显示。 <br/> 3. 不支持[scroller](#waterflowoptions对象说明)的[scrollTo](ts-container-scroll.md#scrollto)接口。 <br/> 4. [scroller](#waterflowoptions对象说明)的[currentOffset](ts-container-scroll.md#currentoffset)接口返回的总偏移量在触发跳转或数据更新后不准确,在回滑到顶部时会重新校准。 <br/> 5. 如果在同一帧内调用跳转(如无动画的[scrollToIndex](ts-container-scroll.md#scrolltoindex)、[scrollEdge](ts-container-scroll.md#scrolledge))和输入偏移量(如滑动手势或滚动动画),两者都会生效。 <br/> 6. 调用无动画的[scrollToIndex](ts-container-scroll.md#scrolltoindex)进行跳转,如果跳转到较远位置(超过视窗内的FlowItem数量的位置)时,由于移动窗口模式对总偏移量没有估算,此时总偏移量没有变化,所以不会触发[onDidScroll](ts-container-scroll.md#ondidscroll12)事件。 |
218
219
220## 属性
221
222除支持[通用属性](ts-universal-attributes-size.md)和[滚动组件通用属性](ts-container-scrollable-common.md#属性)外,还支持以下属性:
223
224### columnsTemplate
225
226columnsTemplate(value: string)
227
228设置当前瀑布流组件布局列的数量,不设置时默认1列。
229
230例如, '1fr 1fr 2fr' 是将父组件分3列,将父组件允许的宽分为4等份,第一列占1份,第二列占1份,第三列占2份。
231
232可使用columnsTemplate('repeat(auto-fill,track-size)')根据给定的列宽track-size自动计算列数,其中repeat、auto-fill为关键字,track-size为可设置的宽度,支持的单位包括px、vp、%或有效数字,默认单位为vp,使用方法参见示例2。
233
234**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
235
236**系统能力:** SystemCapability.ArkUI.ArkUI.Full
237
238**参数:**
239
240| 参数名 | 类型   | 必填 | 说明                                           |
241| ------ | ------ | ---- | ---------------------------------------------- |
242| value  | string | 是   | 当前瀑布流组件布局列的数量。<br/>默认值:'1fr' |
243
244### rowsTemplate
245
246rowsTemplate(value: string)
247
248设置当前瀑布流组件布局行的数量,不设置时默认1行。
249
250例如, '1fr 1fr 2fr'是将父组件分三行,将父组件允许的高分为4等份,第一行占1份,第二行占一份,第三行占2份。
251
252可使用rowsTemplate('repeat(auto-fill,track-size)')根据给定的行高track-size自动计算行数,其中repeat、auto-fill为关键字,track-size为可设置的高度,支持的单位包括px、vp、%或有效数字,默认单位为vp。
253
254**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
255
256**系统能力:** SystemCapability.ArkUI.ArkUI.Full
257
258**参数:**
259
260| 参数名 | 类型   | 必填 | 说明                                           |
261| ------ | ------ | ---- | ---------------------------------------------- |
262| value  | string | 是   | 当前瀑布流组件布局行的数量。<br/>默认值:'1fr' |
263
264### itemConstraintSize
265
266itemConstraintSize(value: ConstraintSizeOptions)
267
268设置约束尺寸,子组件布局时,进行尺寸范围限制。
269
270**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
271
272**系统能力:** SystemCapability.ArkUI.ArkUI.Full
273
274**参数:**
275
276| 参数名 | 类型                                                       | 必填 | 说明       |
277| ------ | ---------------------------------------------------------- | ---- | ---------- |
278| value  | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | 是   | 约束尺寸。设置小于0的值,参数不生效。 <br/>**说明:**<br/>1.同时设置itemConstraintSize和FlowItem的[constraintSize](ts-universal-attributes-size.md#constraintsize)属性时,minWidth/minHeight会取其中的最大值,maxWidth/maxHeight会取其中的最小值,调整后的值作为FlowItem的constraintSize处理。2.只设置itemConstraintSize时,相当于对WaterFlow所有子组件设置了相同的constraintSize。3.itemConstraintSize通过以上两种方式转换成FlowItem的constraintSize后的生效规则与通用属性[constraintSize](./ts-universal-attributes-size.md#constraintsize)相同。|
279
280### columnsGap
281
282columnsGap(value: Length)
283
284设置列与列的间距。
285
286**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
287
288**系统能力:** SystemCapability.ArkUI.ArkUI.Full
289
290**参数:**
291
292| 参数名 | 类型                         | 必填 | 说明                          |
293| ------ | ---------------------------- | ---- | ----------------------------- |
294| value  | [Length](ts-types.md#length) | 是   | 列与列的间距。 <br/>默认值:0 |
295
296### rowsGap
297
298rowsGap(value: Length)
299
300设置行与行的间距。
301
302**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
303
304**系统能力:** SystemCapability.ArkUI.ArkUI.Full
305
306**参数:**
307
308| 参数名 | 类型                         | 必填 | 说明                          |
309| ------ | ---------------------------- | ---- | ----------------------------- |
310| value  | [Length](ts-types.md#length) | 是   | 行与行的间距。 <br/>默认值:0 |
311
312### layoutDirection
313
314layoutDirection(value: FlexDirection)
315
316设置布局的主轴方向。
317
318**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
319
320**系统能力:** SystemCapability.ArkUI.ArkUI.Full
321
322**参数:**
323
324| 参数名 | 类型                                                | 必填 | 说明                                              |
325| ------ | --------------------------------------------------- | ---- | ------------------------------------------------- |
326| value  | [FlexDirection](ts-appendix-enums.md#flexdirection) | 是   | 布局的主轴方向。<br/>默认值:FlexDirection.Column |
327
328layoutDirection优先级高于rowsTemplate和columnsTemplate。根据layoutDirection设置情况,分为以下三种设置模式:
329
330- layoutDirection设置纵向布局(FlexDirection.ColumnFlexDirection.ColumnReverse331
332  此时columnsTemplate有效(如果未设置,取默认值)。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件纵向布局,辅轴均分成横向2列。
333
334- layoutDirection设置横向布局(FlexDirection.RowFlexDirection.RowReverse335
336  此时rowsTemplate有效(如果未设置,取默认值)。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件横向布局,辅轴均分成纵向3列。
337
338- layoutDirection未设置布局方向
339
340  布局方向为layoutDirection的默认值:FlexDirection.Column,此时columnsTemplate有效。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件纵向布局,辅轴均分成横向2列。
341
342### enableScrollInteraction<sup>10+</sup>
343
344enableScrollInteraction(value: boolean)
345
346设置是否支持滚动手势,当设置为false时,无法通过手指或者鼠标滚动,但不影响控制器的滚动接口。
347
348**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
349
350**系统能力:** SystemCapability.ArkUI.ArkUI.Full
351
352**参数:**
353
354| 参数名 | 类型    | 必填 | 说明                                |
355| ------ | ------- | ---- | ----------------------------------- |
356| value  | boolean | 是   | 是否支持滚动手势。<br/>默认值:true |
357
358### nestedScroll<sup>10+</sup>
359
360nestedScroll(value: NestedScrollOptions)
361
362设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。
363
364**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
365
366**系统能力:** SystemCapability.ArkUI.ArkUI.Full
367
368**参数:**
369
370| 参数名 | 类型                                                         | 必填 | 说明           |
371| ------ | ------------------------------------------------------------ | ---- | -------------- |
372| value  | [NestedScrollOptions](ts-container-scrollable-common.md#nestedscrolloptions10对象说明) | 是   | 嵌套滚动选项。 |
373
374### friction<sup>10+</sup>
375
376friction(value: number | Resource)
377
378设置摩擦系数,手动划动滚动区域时生效,只对惯性滚动过程有影响,对惯性滚动过程中的链式效果有间接影响。设置为小于等于0的值时,按默认值处理。
379
380**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
381
382**系统能力:** SystemCapability.ArkUI.ArkUI.Full
383
384**参数:**
385
386| 参数名 | 类型                                                 | 必填 | 说明                                                      |
387| ------ | ---------------------------------------------------- | ---- | --------------------------------------------------------- |
388| value  | number&nbsp;\|&nbsp;[Resource](ts-types.md#resource) | 是   | 摩擦系数。<br/>默认值:非可穿戴设备为0.6,可穿戴设备为0.9。<br/>从API version 11开始,非可穿戴设备默认值为0.7。<br/>从API version 12开始,非可穿戴设备默认值为0.75。 |
389
390### cachedCount<sup>11+</sup>
391
392cachedCount(value: number)
393
394设置预加载的FlowItem的数量,只在LazyForEach中生效。设置该属性后会缓存cachedCount个FlowItem。[LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md)超出显示和缓存范围的FlowItem会被释放。设置为小于0的值时,按默认值显示。
395
396**原子化服务API:** 从API version 12开始,该接口支持在原子化服务中使用。
397
398**系统能力:** SystemCapability.ArkUI.ArkUI.Full
399
400**参数:**
401
402| 参数名 | 类型   | 必填 | 说明                                                         |
403| ------ | ------ | ---- | ------------------------------------------------------------ |
404| value  | number | 是   | 预加载的FlowItem的数量。 <br/> 默认值:根据屏幕内显示的节点个数设置,最大值为16。 |
405
406### cachedCount<sup>14+</sup>
407
408cachedCount(count: number, show: boolean)
409
410设置预加载的FlowItem数量,并配置是否显示预加载节点。
411
412配合[裁剪](ts-universal-attributes-sharp-clipping.md#clip12)或[内容裁剪](ts-container-scrollable-common.md#clipcontent14)属性可以显示出预加载节点。
413
414[LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md)和开启了virtualScroll开关的[Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md)超出显示和缓存范围的FlowItem会被释放。
415
416**原子化服务API:** 从API version 14开始,该接口支持在原子化服务中使用。
417
418**系统能力:** SystemCapability.ArkUI.ArkUI.Full
419
420**参数:**
421
422| 参数名 | 类型   | 必填 | 说明                                     |
423| ------ | ------ | ---- | ---------------------------------------- |
424| count  | number | 是   | 预加载的FlowItem的数量。 <br/> 默认值:根据屏幕内显示的节点个数设置,最大值为16。 |
425| show  | boolean | 是   | 被预加载的FlowItem是否需要显示。 <br/> 默认值:false |
426
427## 事件
428
429除支持[通用事件](ts-universal-events-click.md)和[滚动组件通用事件](ts-container-scrollable-common.md#事件)外,还支持以下事件:
430
431### onReachStart
432
433onReachStart(event: () => void)
434
435瀑布流组件到达起始位置时触发。
436
437**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
438
439**系统能力:** SystemCapability.ArkUI.ArkUI.Full
440
441### onReachEnd
442
443onReachEnd(event: () => void)
444
445瀑布流组件到底末尾位置时触发。
446
447**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
448
449**系统能力:** SystemCapability.ArkUI.ArkUI.Full
450
451### onScrollFrameBegin<sup>10+</sup>
452
453onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number; })
454
455瀑布流开始滑动时触发,事件参数传入即将发生的滑动量,事件处理函数中可根据应用场景计算实际需要的滑动量并作为事件处理函数的返回值返回,瀑布流将按照返回值的实际滑动量进行滑动。
456
457触发该事件的条件:手指拖动WaterFlow、WaterFlow惯性划动时每帧开始时触发;WaterFlow超出边缘回弹、使用滚动控制器和拖动滚动条的滚动不会触发。
458
459**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
460
461**系统能力:** SystemCapability.ArkUI.ArkUI.Full
462
463**参数:**
464
465| 参数名 | 类型                                                    | 必填 | 说明                       |
466| ------ | ------------------------------------------------------- | ---- | -------------------------- |
467| offset | number                                                  | 是   | 即将发生的滑动量,单位vp。 |
468| state  | [ScrollState](ts-container-list.md#scrollstate枚举说明) | 是   | 当前滑动状态。             |
469
470**返回值:**
471
472| 类型                     | 说明                 |
473| ------------------------ | -------------------- |
474| { offsetRemain: number } | 实际滑动量,单位vp。 |
475
476### onScrollIndex<sup>11+</sup>
477
478onScrollIndex(event: (first: number, last: number) => void)
479
480当前瀑布流显示的起始位置/终止位置的子组件发生变化时触发。瀑布流初始化时会触发一次。
481
482瀑布流显示区域上第一个子组件/最后一个组件的索引值有变化就会触发。
483
484**原子化服务API:** 从API version 11开始,该接口支持在原子化服务中使用。
485
486**系统能力:** SystemCapability.ArkUI.ArkUI.Full
487
488**参数:**
489
490| 参数名 | 类型   | 必填 | 说明                                  |
491| ------ | ------ | ---- | ------------------------------------- |
492| first  | number | 是   | 当前显示的瀑布流起始位置的索引值。 |
493| last   | number | 是   | 当前显示的瀑布流终止位置的索引值。    |
494
495## 示例
496
497### 示例1(使用基本瀑布流)
498该示例展示了WaterFlow组件数据加载处理、属性设置和事件回调等基本使用场景。
499```ts
500// WaterFlowDataSource.ets
501
502// 实现IDataSource接口的对象,用于瀑布流组件加载数据
503export class WaterFlowDataSource implements IDataSource {
504  private dataArray: number[] = []
505  private listeners: DataChangeListener[] = []
506
507  constructor() {
508    for (let i = 0; i < 100; i++) {
509      this.dataArray.push(i)
510    }
511  }
512
513  // 获取索引对应的数据
514  public getData(index: number): number {
515    return this.dataArray[index]
516  }
517
518  // 通知控制器数据重新加载
519  notifyDataReload(): void {
520    this.listeners.forEach(listener => {
521      listener.onDataReloaded()
522    })
523  }
524
525  // 通知控制器数据增加
526  notifyDataAdd(index: number): void {
527    this.listeners.forEach(listener => {
528      listener.onDataAdd(index)
529    })
530  }
531
532  // 通知控制器数据变化
533  notifyDataChange(index: number): void {
534    this.listeners.forEach(listener => {
535      listener.onDataChange(index)
536    })
537  }
538
539  // 通知控制器数据删除
540  notifyDataDelete(index: number): void {
541    this.listeners.forEach(listener => {
542      listener.onDataDelete(index)
543    })
544  }
545
546  // 通知控制器数据位置变化
547  notifyDataMove(from: number, to: number): void {
548    this.listeners.forEach(listener => {
549      listener.onDataMove(from, to)
550    })
551  }
552
553  //通知控制器数据批量修改
554  notifyDatasetChange(operations: DataOperation[]): void {
555    this.listeners.forEach(listener => {
556      listener.onDatasetChange(operations);
557    })
558  }
559
560  // 获取数据总数
561  public totalCount(): number {
562    return this.dataArray.length
563  }
564
565  // 注册改变数据的控制器
566  registerDataChangeListener(listener: DataChangeListener): void {
567    if (this.listeners.indexOf(listener) < 0) {
568      this.listeners.push(listener)
569    }
570  }
571
572  // 注销改变数据的控制器
573  unregisterDataChangeListener(listener: DataChangeListener): void {
574    const pos = this.listeners.indexOf(listener)
575    if (pos >= 0) {
576      this.listeners.splice(pos, 1)
577    }
578  }
579
580  // 增加数据
581  public add1stItem(): void {
582    this.dataArray.splice(0, 0, this.dataArray.length)
583    this.notifyDataAdd(0)
584  }
585
586  // 在数据尾部增加一个元素
587  public addLastItem(): void {
588    this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length)
589    this.notifyDataAdd(this.dataArray.length - 1)
590  }
591
592  // 在指定索引位置增加一个元素
593  public addItem(index: number): void {
594    this.dataArray.splice(index, 0, this.dataArray.length)
595    this.notifyDataAdd(index)
596  }
597
598  // 删除第一个元素
599  public delete1stItem(): void {
600    this.dataArray.splice(0, 1)
601    this.notifyDataDelete(0)
602  }
603
604  // 删除第二个元素
605  public delete2ndItem(): void {
606    this.dataArray.splice(1, 1)
607    this.notifyDataDelete(1)
608  }
609
610  // 删除最后一个元素
611  public deleteLastItem(): void {
612    this.dataArray.splice(-1, 1)
613    this.notifyDataDelete(this.dataArray.length)
614  }
615
616  // 在指定索引位置删除一个元素
617  public deleteItem(index: number): void {
618    this.dataArray.splice(index, 1)
619    this.notifyDataDelete(index)
620  }
621
622  // 重新加载数据
623  public reload(): void {
624    this.dataArray.splice(1, 1)
625    this.dataArray.splice(3, 2)
626    this.notifyDataReload()
627  }
628}
629```
630
631```ts
632// Index.ets
633import { WaterFlowDataSource } from './WaterFlowDataSource'
634
635@Entry
636@Component
637struct WaterFlowDemo {
638  @State minSize: number = 80
639  @State maxSize: number = 180
640  @State fontSize: number = 24
641  @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
642  scroller: Scroller = new Scroller()
643  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
644  private itemWidthArray: number[] = []
645  private itemHeightArray: number[] = []
646
647  // 计算FlowItem宽/高
648  getSize() {
649    let ret = Math.floor(Math.random() * this.maxSize)
650    return (ret > this.minSize ? ret : this.minSize)
651  }
652
653  // 设置FlowItem的宽/高数组
654  setItemSizeArray() {
655    for (let i = 0; i < 100; i++) {
656      this.itemWidthArray.push(this.getSize())
657      this.itemHeightArray.push(this.getSize())
658    }
659  }
660
661  aboutToAppear() {
662    this.setItemSizeArray()
663  }
664
665  @Builder
666  itemFoot() {
667    Column() {
668      Text(`Footer`)
669        .fontSize(10)
670        .backgroundColor(Color.Red)
671        .width(50)
672        .height(50)
673        .align(Alignment.Center)
674        .margin({ top: 2 })
675    }
676  }
677
678  build() {
679    Column({ space: 2 }) {
680      WaterFlow() {
681        LazyForEach(this.dataSource, (item: number) => {
682          FlowItem() {
683            Column() {
684              Text("N" + item).fontSize(12).height('16')
685              // 存在对应的jpg文件才会显示图片
686              Image('res/waterFlowTest(' + item % 5 + ').jpg')
687                .objectFit(ImageFit.Fill)
688                .width('100%')
689                .layoutWeight(1)
690            }
691          }
692          .onAppear(() => {
693            // 即将触底时提前增加数据
694            if (item + 20 == this.dataSource.totalCount()) {
695              for (let i = 0; i < 100; i++) {
696                this.dataSource.addLastItem()
697              }
698            }
699          })
700          .width('100%')
701          .height(this.itemHeightArray[item % 100])
702          .backgroundColor(this.colors[item % 5])
703        }, (item: string) => item)
704      }
705      .columnsTemplate("1fr 1fr")
706      .columnsGap(10)
707      .rowsGap(5)
708      .backgroundColor(0xFAEEE0)
709      .width('100%')
710      .height('100%')
711      .onReachStart(() => {
712        console.info('waterFlow reach start')
713      })
714      .onScrollStart(() => {
715        console.info('waterFlow scroll start')
716      })
717      .onScrollStop(() => {
718        console.info('waterFlow scroll stop')
719      })
720      .onScrollFrameBegin((offset: number, state: ScrollState) => {
721        console.info('waterFlow scrollFrameBegin offset: ' + offset + ' state: ' + state.toString())
722        return { offsetRemain: offset }
723      })
724    }
725  }
726}
727```
728
729![zh-cn_image_WaterFlow.gif](figures/waterflow-perf-demo.gif)
730
731### 示例2(自动计算列数)
732该示例通过auto-fill实现了自动计算列数的效果。
733```ts
734// Index.ets
735import { WaterFlowDataSource } from './WaterFlowDataSource'
736
737@Entry
738@Component
739struct WaterFlowDemo {
740  @State minSize: number = 80
741  @State maxSize: number = 180
742  @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
743  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
744  private itemWidthArray: number[] = []
745  private itemHeightArray: number[] = []
746
747  // 计算FlowItem宽/高
748  getSize() {
749    let ret = Math.floor(Math.random() * this.maxSize)
750    return (ret > this.minSize ? ret : this.minSize)
751  }
752
753  // 设置FlowItem宽/高数组
754  setItemSizeArray() {
755    for (let i = 0; i < 100; i++) {
756      this.itemWidthArray.push(this.getSize())
757      this.itemHeightArray.push(this.getSize())
758    }
759  }
760
761  aboutToAppear() {
762    this.setItemSizeArray()
763  }
764
765  build() {
766    Column({ space: 2 }) {
767      WaterFlow() {
768        LazyForEach(this.dataSource, (item: number) => {
769          FlowItem() {
770            Column() {
771              Text("N" + item).fontSize(12).height('16')
772              Image('res/waterFlowTest(' + item % 5 + ').jpg')
773            }
774          }
775          .width('100%')
776          .height(this.itemHeightArray[item % 100])
777          .backgroundColor(this.colors[item % 5])
778        }, (item: string) => item)
779      }
780      .columnsTemplate('repeat(auto-fill,80)')
781      .columnsGap(10)
782      .rowsGap(5)
783      .padding({left:5})
784      .backgroundColor(0xFAEEE0)
785      .width('100%')
786      .height('100%')
787    }
788  }
789}
790```
791
792![waterflow_auto-fill.png](figures/waterflow_auto-fill.png)
793
794
795### 示例3(使用分组)
796该示例展示了分组的初始化以及splice、push、update、values、length等接口的不同效果。
797如果配合状态管理V2使用,详情见:[WaterFlow与makeObserved](../../../quick-start/arkts-v1-v2-migration.md#waterflow)。
798```ts
799// Index.ets
800import { WaterFlowDataSource } from './WaterFlowDataSource'
801
802@Reusable
803@Component
804struct ReusableFlowItem {
805  @State item: number = 0
806
807  // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容
808  aboutToReuse(params: Record<string, number>) {
809    this.item = params.item;
810    console.info('Reuse item:' + this.item)
811  }
812
813  aboutToAppear() {
814    console.info('new item:' + this.item)
815  }
816
817  build() {
818    Image('res/waterFlowTest(' + this.item % 5 + ').jpg')
819        .overlay('N' + this.item, { align: Alignment.Top })
820        .objectFit(ImageFit.Fill)
821        .width('100%')
822        .layoutWeight(1)
823  }
824}
825
826@Entry
827@Component
828struct WaterFlowDemo {
829  minSize: number = 80
830  maxSize: number = 180
831  fontSize: number = 24
832  colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
833  scroller: Scroller = new Scroller()
834  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
835  dataCount: number = this.dataSource.totalCount()
836  private itemHeightArray: number[] = []
837  @State sections: WaterFlowSections = new WaterFlowSections()
838  sectionMargin: Margin = { top: 10, left: 5, bottom: 10, right: 5 }
839  oneColumnSection: SectionOptions = {
840    itemsCount: 4,
841    crossCount: 1,
842    columnsGap: '5vp',
843    rowsGap: 10,
844    margin: this.sectionMargin,
845    onGetItemMainSizeByIndex: (index: number) => {
846      return this.itemHeightArray[index % 100]
847    }
848  }
849  twoColumnSection: SectionOptions = {
850    itemsCount: 2,
851    crossCount: 2,
852    onGetItemMainSizeByIndex: (index: number) => {
853      return 100
854    }
855  }
856  lastSection: SectionOptions = {
857    itemsCount: 20,
858    crossCount: 2,
859    onGetItemMainSizeByIndex: (index: number) => {
860      return this.itemHeightArray[index % 100]
861    }
862  }
863
864  // 计算FlowItem高度
865  getSize() {
866    let ret = Math.floor(Math.random() * this.maxSize)
867    return (ret > this.minSize ? ret : this.minSize)
868  }
869
870  // 设置FlowItem的高度数组
871  setItemSizeArray() {
872    for (let i = 0; i < 100; i++) {
873      this.itemHeightArray.push(this.getSize())
874    }
875  }
876
877  aboutToAppear() {
878    this.setItemSizeArray()
879    // 初始化瀑布流分组信息
880    let sectionOptions: SectionOptions[] = []
881    let count = 0
882    let oneOrTwo = 0
883    while (count < this.dataCount) {
884      if (this.dataCount - count < 20) {
885        this.lastSection.itemsCount = this.dataCount - count
886        sectionOptions.push(this.lastSection)
887        break;
888      }
889      if (oneOrTwo++ % 2 == 0) {
890        sectionOptions.push(this.oneColumnSection)
891        count += this.oneColumnSection.itemsCount
892      } else {
893        sectionOptions.push(this.twoColumnSection)
894        count += this.twoColumnSection.itemsCount
895      }
896    }
897    this.sections.splice(0, 0, sectionOptions)
898  }
899
900  build() {
901    Column({ space: 2 }) {
902      Row() {
903        Button('splice')
904          .height('5%')
905          .onClick(() => {
906            // 将所有分组替换成一个新分组,注意保证LazyForEach中数据数量和新分组itemsCount保持一致
907            let totalCount: number = this.dataSource.totalCount()
908            let newSection: SectionOptions = {
909              itemsCount: totalCount,
910              crossCount: 2,
911              onGetItemMainSizeByIndex: (index: number) => {
912                return this.itemHeightArray[index % 100]
913              }
914            }
915            let oldLength: number = this.sections.length()
916            this.sections.splice(0, oldLength, [newSection])
917          })
918          .margin({ top: 10, left: 20 })
919        Button('update')
920          .height('5%')
921          .onClick(() => {
922            // 在第二个分组增加4个FlowItem,注意保证LazyForEach中数据数量和所有分组itemsCount的和保持一致
923            let newSection: SectionOptions = {
924              itemsCount: 6,
925              crossCount: 3,
926              columnsGap: 5,
927              rowsGap: 10,
928              margin: this.sectionMargin,
929              onGetItemMainSizeByIndex: (index: number) => {
930                return this.itemHeightArray[index % 100]
931              }
932            }
933            this.dataSource.addItem(this.oneColumnSection.itemsCount)
934            this.dataSource.addItem(this.oneColumnSection.itemsCount + 1)
935            this.dataSource.addItem(this.oneColumnSection.itemsCount + 2)
936            this.dataSource.addItem(this.oneColumnSection.itemsCount + 3)
937            const result: boolean = this.sections.update(1, newSection)
938            console.info('update:' + result)
939          })
940          .margin({ top: 10, left: 20 })
941        Button('delete')
942          .height('5%')
943          .onClick(() => {
944            // 先点击update再点击delete
945            let newSection: SectionOptions = {
946              itemsCount: 2,
947              crossCount: 2,
948              columnsGap: 5,
949              rowsGap: 10,
950              margin: this.sectionMargin,
951              onGetItemMainSizeByIndex: (index: number) => {
952                return this.itemHeightArray[index % 100]
953              }
954            }
955            this.dataSource.deleteItem(this.oneColumnSection.itemsCount)
956            this.dataSource.deleteItem(this.oneColumnSection.itemsCount)
957            this.dataSource.deleteItem(this.oneColumnSection.itemsCount)
958            this.dataSource.deleteItem(this.oneColumnSection.itemsCount)
959            this.sections.update(1, newSection)
960          })
961          .margin({ top: 10, left: 20 })
962        Button('values')
963          .height('5%')
964          .onClick(() => {
965            const sections: Array<SectionOptions> = this.sections.values();
966            for (const value of sections) {
967              console.log(JSON.stringify(value));
968            }
969            console.info('count:' + this.sections.length())
970          })
971          .margin({ top: 10, left: 20 })
972      }.margin({ bottom: 20 })
973
974      WaterFlow({ scroller: this.scroller, sections: this.sections }) {
975        LazyForEach(this.dataSource, (item: number) => {
976          FlowItem() {
977            ReusableFlowItem({ item: item })
978          }
979          .width('100%')
980          // 以onGetItemMainSizeByIndex为准
981          // .height(this.itemHeightArray[item % 100])
982          .backgroundColor(this.colors[item % 5])
983        }, (item: string) => item)
984      }
985      .columnsTemplate('1fr 1fr') // 瀑布流使用sections参数时该属性无效
986      .columnsGap(10)
987      .rowsGap(5)
988      .backgroundColor(0xFAEEE0)
989      .width('100%')
990      .height('100%')
991      .layoutWeight(1)
992      .onScrollIndex((first: number, last: number) => {
993        // 即将触底时提前增加数据
994        if (last + 20 >= this.dataSource.totalCount()) {
995          for (let i = 0; i < 100; i++) {
996            this.dataSource.addLastItem()
997          }
998          // 更新数据源后同步更新sections,修改最后一个section的FlowItem数量
999          const sections: Array<SectionOptions> = this.sections.values();
1000          let newSection: SectionOptions = sections[this.sections.length() - 1];
1001          newSection.itemsCount += 100;
1002          this.sections.update(-1, newSection);
1003        }
1004      })
1005    }
1006  }
1007}
1008```
1009
1010![waterflowSections.png](figures/waterflowSections.png)
1011
1012### 示例4(双指缩放改变列数)
1013该示例通过[priorityGesture](ts-gesture-settings.md)和[PinchGesture](ts-basic-gestures-pinchgesture.md)实现了双指缩放改变列数效果。
1014```ts
1015// Index.ets
1016import { WaterFlowDataSource } from './WaterFlowDataSource'
1017
1018@Reusable
1019@Component
1020struct ReusableFlowItem {
1021  @State item: number = 0
1022
1023  // 从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容
1024  aboutToReuse(params: Record<string, number>) {
1025    this.item = params.item;
1026    console.info('Reuse item:' + this.item)
1027  }
1028
1029  aboutToAppear() {
1030    console.info('item:' + this.item)
1031  }
1032
1033  build() {
1034    Column() {
1035      Text("N" + this.item).fontSize(12).height('16')
1036      Image('res/waterFlow (' + this.item % 5 + ').JPG')
1037        .objectFit(ImageFit.Fill)
1038        .width('100%')
1039        .layoutWeight(1)
1040    }
1041  }
1042}
1043
1044@Entry
1045@Component
1046struct WaterFlowDemo {
1047  minSize: number = 80
1048  maxSize: number = 180
1049  colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
1050  @State columns: number = 2
1051  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
1052  private itemWidthArray: number[] = []
1053  private itemHeightArray: number[] = []
1054
1055  // 计算FlowItem宽/高
1056  getSize() {
1057    let ret = Math.floor(Math.random() * this.maxSize)
1058    return (ret > this.minSize ? ret : this.minSize)
1059  }
1060
1061  // 设置FlowItem的宽/高数组
1062  setItemSizeArray() {
1063    for (let i = 0; i < 100; i++) {
1064      this.itemWidthArray.push(this.getSize())
1065      this.itemHeightArray.push(this.getSize())
1066    }
1067  }
1068
1069  aboutToAppear() {
1070    let lastCount = AppStorage.get<number>('columnsCount')
1071    if (typeof lastCount != 'undefined') {
1072      this.columns = lastCount
1073    }
1074    this.setItemSizeArray()
1075  }
1076
1077  build() {
1078    Column({ space: 2 }) {
1079      Row() {
1080        Text('双指缩放改变列数')
1081          .height('5%')
1082          .margin({ top: 10, left: 20 })
1083      }
1084
1085      WaterFlow() {
1086        LazyForEach(this.dataSource, (item: number) => {
1087          FlowItem() {
1088            ReusableFlowItem({ item: item })
1089          }
1090          .width('100%')
1091          .height(this.itemHeightArray[item % 100])
1092          .backgroundColor(this.colors[item % 5])
1093        }, (item: string) => item)
1094      }
1095      .columnsTemplate('1fr '.repeat(this.columns))
1096      .columnsGap(10)
1097      .rowsGap(5)
1098      .backgroundColor(0xFAEEE0)
1099      .width('100%')
1100      .height('100%')
1101      .layoutWeight(1)
1102      // 切换列数item位置重排动画
1103      .animation({
1104        duration: 300,
1105        curve: Curve.Smooth
1106      })
1107      .priorityGesture(
1108        PinchGesture()
1109          .onActionEnd((event: GestureEvent) => {
1110            console.info('end scale:' + event.scale)
1111            // 手指分开,减少列数以放大item,触发阈值可以自定义,示例为2
1112            if (event.scale > 2) {
1113              this.columns--
1114            } else if (event.scale < 0.6) {
1115              this.columns++
1116            }
1117            // 可以根据设备屏幕宽度设定最大和最小列数,此处以最小1列最大4列为例
1118            this.columns = Math.min(4, Math.max(1, this.columns));
1119            AppStorage.setOrCreate<number>('columnsCount', this.columns)
1120          })
1121      )
1122    }
1123  }
1124}
1125```
1126
1127![pinch](figures/waterflow-pinch.gif)
1128
1129### 示例5(设置边缘渐隐效果)
1130该示例通过[fadingEdge](ts-container-scrollable-common.md#fadingedge14)实现了WaterFlow组件开启边缘渐隐效果,并通过fadingEdgeLength参数设置边缘渐隐长度。
1131```ts
1132// Index.ets
1133import { LengthMetrics } from '@kit.ArkUI'
1134import { WaterFlowDataSource } from './WaterFlowDataSource'
1135@Entry
1136@Component
1137struct WaterFlowDemo {
1138  @State minSize: number = 80
1139  @State maxSize: number = 180
1140  @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
1141  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
1142  scroller: Scroller = new Scroller()
1143  private itemWidthArray: number[] = []
1144  private itemHeightArray: number[] = []
1145
1146  // 计算FlowItem宽/高
1147  getSize() {
1148    let ret = Math.floor(Math.random() * this.maxSize)
1149    return (ret > this.minSize ? ret : this.minSize)
1150  }
1151
1152  // 设置FlowItem宽/高数组
1153  setItemSizeArray() {
1154    for (let i = 0; i < 100; i++) {
1155      this.itemWidthArray.push(this.getSize())
1156      this.itemHeightArray.push(this.getSize())
1157    }
1158  }
1159
1160  aboutToAppear() {
1161    this.setItemSizeArray()
1162  }
1163
1164  build() {
1165    Column({ space: 2 }) {
1166
1167      WaterFlow({ scroller:this.scroller }) {
1168        LazyForEach(this.dataSource, (item: number) => {
1169          FlowItem() {
1170            Column() {
1171              Text("N" + item).fontSize(12).height('16')
1172            }
1173          }
1174          .width('100%')
1175          .height(this.itemHeightArray[item % 100])
1176          .backgroundColor(this.colors[item % 5])
1177        }, (item: string) => item)
1178      }
1179      .columnsTemplate('repeat(auto-fill,80)')
1180      .columnsGap(10)
1181      .rowsGap(5)
1182      .height('90%')
1183      .scrollBar(BarState.On)
1184      .fadingEdge(true,{fadingEdgeLength:LengthMetrics.vp(80)})
1185
1186    }
1187  }
1188}
1189```
1190
1191![fadingEdge_waterFlow](figures/fadingEdge_waterFlow.gif)