1# WaterFlow 2 3 4The **WaterFlow** component is a water flow container that consists of cells formed by rows and columns and arranges items of different sizes from top to bottom according to the preset rules. 5 6 7> **NOTE** 8> 9> This component is supported since API version 9. Updates will be marked with a superscript to indicate their earliest API version. 10 11 12## Child Components 13 14 15Only the [FlowItem](ts-container-flowitem.md) child component is allowed, with support for [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), and [Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md) rendering control. 16 17> **NOTE** 18> 19> When its **visibility** attribute is set to **None**, a **FlowItem** is not displayed in the container, but its **columnsGap**, **rowsGap**, and **margin** settings are still effective. 20 21## APIs 22 23WaterFlow(options?: WaterFlowOptions) 24 25Creates a **WaterFlow** component. 26 27**Atomic service API**: This API can be used in atomic services since API version 11. 28 29**System capability**: SystemCapability.ArkUI.ArkUI.Full 30 31**Parameters** 32 33| Name| Type| Mandatory| Description| 34| -------- | -------- | -------- | -------- | 35| options | [WaterFlowOptions](#waterflowoptions)| No| Parameters of the **WaterFlow** component.| 36 37 38## WaterFlowOptions 39 40Provides parameters of the **WaterFlow** component. 41 42**System capability**: SystemCapability.ArkUI.ArkUI.Full 43 44| Name | Type | Mandatory| Description | 45| ---------- | ----------------------------------------------- | ------ | -------------------------------------------- | 46| footer | [CustomBuilder](ts-types.md#custombuilder8) | No | Footer of the **WaterFlow** component.<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 47| scroller | [Scroller](ts-container-scroll.md#scroller) | No | Controller of the scrollable component, bound to the scrollable component.<br>**NOTE**<br>The same scroller cannot be bound to other scrollable components, such as [List](ts-container-list.md), [Grid](ts-container-grid.md), or [Scroll](ts-container-scroll.md).<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 48| sections<sup>12+</sup> | [WaterFlowSections](#waterflowsections12) | No | Water flow item sections. Different sections can have different numbers of columns.<br>**NOTE**<br>1. When **sections** is used, the **columnsTemplate** and **rowsTemplate** attributes are ignored.<br>2. When **sections** is used, the footer cannot be set separately. The last section can function as the footer.<br>**Atomic service API**: This API can be used in atomic services since API version 12. | 49| layoutMode<sup>12+</sup> |[WaterFlowLayoutMode](#waterflowlayoutmode12)| No| Layout mode of the **WaterFlow** component.<br>**NOTE**<br>Default value: [ALWAYS_TOP_DOWN](#waterflowlayoutmode12)<br>**Atomic service API**: This API can be used in atomic services since API version 12. 50 51 52## WaterFlowSections<sup>12+</sup> 53 54Describes the water flow item sections. 55 56> **NOTE** 57> 58> After the section information is modified using **splice**, **push**, and **update**, ensure that the total number of child nodes in all sections matches the actual total number of child nodes in the **WaterFlow** component. Any failure to do so may result in layout issues that prevent the **WaterFlow** component from scrolling properly. 59 60### constructor 61 62constructor() 63 64A constructor used to create a **WaterFlowSections** object. 65 66**Atomic service API**: This API can be used in atomic services since API version 12. 67 68**System capability**: SystemCapability.ArkUI.ArkUI.Full 69 70### splice<sup>12+</sup> 71 72splice(start: number, deleteCount?: number, sections?: Array\<SectionOptions\>): boolean 73 74Changes sections by removing or replacing an existing section and/or adding a section. 75 76**Atomic service API**: This API can be used in atomic services since API version 12. 77 78**System capability**: SystemCapability.ArkUI.ArkUI.Full 79 80**Parameters** 81 82| Name | Type | Mandatory | Description | 83| ---- | ----------------------------- | ---- | -------------------- | 84| start | number | Yes | Zero-based index at which the changing starts. The value is converted to an integer.<br>**NOTE**<br>1. A negative index counts back from the end of the section list. If -**WaterFlowSections.length()** <= **start** < **0**, **start** + **array.length** is used.<br>2. If **start** < -**WaterFlowSections.length()**, **0** is used.<br>3. If **start** >= **WaterFlowSections.length()**, a new section is added at the end.| 85| deleteCount | number | No | Number of sections to be deleted from the position specified by **start**.<br>**NOTE**<br>1. If **deleteCount** is omitted, or if its value is greater than or equal to the number of sections from the position specified by **start** to the end of the **WaterFlowSections**, then all sections from the position specified by **start** to the end of the **WaterFlowSections** will be deleted.<br>2. If **deleteCount** is **0** or a negative number, no sections are deleted.| 86| sections | Array<[SectionOptions](#sectionoptions12)> | No | Sections to add to the section list, beginning from the position specified by **start**. If no section is specified, **splice()** will only delete sections from the **WaterFlow** component.| 87 88**Return value** 89 90| Type | Description | 91| ------------------------------------------------------------ | ------------------------------------------------------------ | 92| boolean | Whether the changing is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 93 94 95### push<sup>12+</sup> 96 97push(section: SectionOptions): boolean 98 99Adds the specified sections to the end of the **WaterFlow** component. 100 101**Atomic service API**: This API can be used in atomic services since API version 12. 102 103**System capability**: SystemCapability.ArkUI.ArkUI.Full 104 105**Parameters** 106 107| Name | Type | Mandatory | Description | 108| ---- | ----------------------------- | ---- | -------------------- | 109| section | [SectionOptions](#sectionoptions12) | Yes | Sections to add to the end of the **WaterFlow** component.| 110 111**Return value** 112 113| Type | Description | 114| ------------------------------------------------------------ | ------------------------------------------------------------ | 115| boolean | Whether the adding is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 116 117### update<sup>12+</sup> 118 119update(sectionIndex: number, section: SectionOptions): boolean 120 121Updates the configuration of a specified water flow item section. 122 123**Atomic service API**: This API can be used in atomic services since API version 12. 124 125**System capability**: SystemCapability.ArkUI.ArkUI.Full 126 127**Parameters** 128 129| Name | Type | Mandatory | Description | 130| ---- | ----------------------------- | ---- | -------------------- | 131| sectionIndex | number | Yes | Zero-based index of the water flow item section to update. The value is converted to an integer.<br>**NOTE**<br>1. A negative index counts back from the end of the section list. If -**WaterFlowSections.length()** <= **sectionIndex** < **0**, **sectionIndex** + **array.length** is used.<br>2. If **sectionIndex** < -**WaterFlowSections.length()**, **0** is used.<br>3. If **sectionIndex** >= **WaterFlowSections.length()**, a new section is added at the end.| 132| section | [SectionOptions](#sectionoptions12) | Yes | New section configuration.| 133 134**Return value** 135 136| Type | Description | 137| ------------------------------------------------------------ | ------------------------------------------------------------ | 138| boolean | Whether the update is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 139 140### values<sup>12+</sup> 141 142values(): Array\<SectionOptions\> 143 144Obtains the configuration of all sections in the **WaterFlow** component. 145 146**Atomic service API**: This API can be used in atomic services since API version 12. 147 148**System capability**: SystemCapability.ArkUI.ArkUI.Full 149 150**Return value** 151 152| Type | Description | 153| ------------------------------------------------------------ | ------------------------------------------------------------ | 154| Array<[SectionOptions](#sectionoptions12)> | Configuration of all sections in the **WaterFlow** component.| 155 156### length<sup>12+</sup> 157 158length(): number 159 160Obtains the number of sections in the **WaterFlow** component. 161 162**Atomic service API**: This API can be used in atomic services since API version 12. 163 164**System capability**: SystemCapability.ArkUI.ArkUI.Full 165 166**Return value** 167 168| Type | Description | 169| ------------------------------------------------------------ | ------------------------------------------------------------ | 170| number | Number of sections in the **WaterFlow** component.| 171 172## SectionOptions<sup>12+</sup> 173 174Describes the configuration of the water flow item section. 175 176**Atomic service API**: This API can be used in atomic services since API version 12. 177 178**System capability**: SystemCapability.ArkUI.ArkUI.Full 179 180| Name| Type| Mandatory| Description| 181|------|-----|-----|-----| 182| itemsCount | number | Yes| Number of water flow items in the section. The value must be a positive integer. If the **splice**, **push**, or **update** APIs receive a section where the **itemsCount** value is less than 0, these APIs will not be executed.| 183| crossCount | number | No| Number of columns (in vertical layout) or rows (in horizontal layout).<br>Default value: **1**<br> If the value is less than 1, the default value is used.| 184| columnsGap | [Dimension](ts-types.md#dimension10) | No| Gap between columns. If this parameter is not set, the value of **columnsGap** for the water flow is used. If this parameter is set to an invalid value, 0 vp is used.| 185| rowsGap | [Dimension](ts-types.md#dimension10) | No| Gap between rows. If this parameter is not set, the value of **rowsGap** for the water flow is used. If this parameter is set to an invalid value, 0 vp is used.| 186| margin | [Margin](ts-types.md#margin) \| [Dimension](ts-types.md#dimension10) | No| Padding of the section. A value of the Length type specifies the margin for all the four sides.<br>Default value: **0**<br>Unit: vp<br>When **margin** is set to a percentage, the width of the **WaterFlow** component is used as the base value for the top, bottom, left, and right margins.| 187| onGetItemMainSizeByIndex | [GetItemMainSizeByIndex](#getitemmainsizebyindex12) | No| Callback used to obtain the main axis size, in vp, of the water flow item at a specified index during the layout process of the **WaterFlow** component. For a vertical **WaterFlow** component, this size refers to the height, and for a horizontal **WaterFlow** component, it refers to the width.<br>**NOTE**<br>1. When both **onGetItemMainSizeByIndex** and the width or height attribute of the water flow item are used, the main axis size is determined by the return value of **onGetItemMainSizeByIndex**, which will override the main axis length of water flow item.<br>2. Using **onGetItemMainSizeByIndex** can improve the efficiency of jumping to a specific position or index in the **WaterFlow** component. Avoid mixing the use of **onGetItemMainSizeByIndex** with sections that do not have it set, as this can cause layout exceptions.<br>3. If **onGetItemMainSizeByIndex** returns a negative number, the height of the water flow item is 0.| 188 189 190## GetItemMainSizeByIndex<sup>12+</sup> 191 192type GetItemMainSizeByIndex = (index: number) => number 193 194Obtains the main axis size of a specified water flow item based on its index. 195 196**Atomic service API**: This API can be used in atomic services since API version 12. 197 198**System capability**: SystemCapability.ArkUI.ArkUI.Full 199 200**Parameters** 201 202| Name | Type | Mandatory | Description | 203| ---- | ----------------------------- | ---- | -------------------- | 204| index | number | Yes | Index of the target water flow item.| 205 206**Return value** 207 208| Type | Description | 209| ------------------------------------------------------------ | ------------------------------------------------------------ | 210| number | Main axis size, in vp, of the water flow item at the specified index, which is the height for a vertical **WaterFlow** component and the width for a horizontal **WaterFlow** component.| 211 212## WaterFlowLayoutMode<sup>12+</sup> 213 214Enumerates the layout modes of the **WaterFlow** component. 215 216**Atomic service API**: This API can be used in atomic services since API version 12. 217 218**System capability**: SystemCapability.ArkUI.ArkUI.Full 219 220| Name| Value| Description| 221| ------ | ------ | -------------------- | 222| ALWAYS_TOP_DOWN | 0 | Default layout mode where water flow items are arranged from top to bottom. Items in the viewport depend on the layout of all items above them. As such, in cases of redirection or switching the number of columns, the layout of all items above the viewport must be recalculated.| 223| SLIDING_WINDOW | 1 | Sliding window mode. This mode only takes into account the layout in the viewport, without depending on water flow items above the viewport. As such, in cases of redirection backward or switching the number of columns, only the water flow items within the viewport need to be laid out. This mode is recommended for applications that involves frequent switching between different numbers of columns.<br>**NOTE**<br>1. During a non-animated redirection to a distant location, water flow items are laid out forward or backward based on the target position. If the user then swipes back to the position prior to the redirection, the layout of the content may not be consistent with its previous state. This can lead to misalignment of the top nodes when the user swipes back to the top after the redirection. To counteract this issue, in this layout mode, the layout will be automatically adjusted after reaching the top of the viewport to ensure that the top is aligned. If there are multiple sections, adjustments will be made to the sections within the viewport when scrolling ends.<br> 2. The mode does not support the use of scrollbars; they will not be displayed even if set.<br> 3. This mode does not support the [scrollTo](ts-container-scroll.md#scrollto) API of [scroller](#waterflowoptions).<br> 4. The total offset returned by the [currentOffset](ts-container-scroll.md#currentoffset) API of [scroller](#waterflowoptions) is inaccurate after a redirection or data update. This offset will be recalibrated when the user swipes back to the top.<br> 5. If a jump action (for example, by calling [scrollToIndex](ts-container-scroll.md#scrolltoindex) without animation or [scrollEdge](ts-container-scroll.md#scrolledge)) and an input offset (such as from a swipe gesture or a scrolling animation) are both initiated within the same frame, both will be executed.<br> 6. If the [scrollToIndex](ts-container-scroll.md#scrolltoindex) API is called without animation to jump to a distant position (beyond the range of visible water flow items in the window), the total offset is not calculated in the sliding window mode, so the total offset remains unchanged. Consequently, the [onDidScroll](ts-container-scroll.md#ondidscroll12) event is not triggered.| 224 225 226## Attributes 227 228In addition to [universal attributes](ts-component-general-attributes.md) and [scrollable component common attributes](ts-container-scrollable-common.md#attributes), the following attributes are also supported. 229 230### columnsTemplate 231 232columnsTemplate(value: string) 233 234Sets the number of columns in the layout. If this attribute is not set, one column is used by default. 235 236For example, **'1fr 1fr 2fr'** indicates three columns, with the first column taking up 1/4 of the parent component's full width, the second column 1/4, and the third column 2/4. 237 238You can use **columnsTemplate('repeat(auto-fill,track-size)')** to automatically calculate the number of columns based on the specified column width **track-size**. **repeat** and **auto-fill** are keywords. The units for **track-size** can be px, vp (default), %, or a valid number. For details, see Example 2. 239 240**Atomic service API**: This API can be used in atomic services since API version 11. 241 242**System capability**: SystemCapability.ArkUI.ArkUI.Full 243 244**Parameters** 245 246| Name| Type | Mandatory| Description | 247| ------ | ------ | ---- | ---------------------------------------------- | 248| value | string | Yes | Number of columns in the layout.<br>Default value: **'1fr'**| 249 250### rowsTemplate 251 252rowsTemplate(value: string) 253 254Sets the number of rows in the layout. If this attribute is not set, one row is used by default. 255 256For example, **'1fr 1fr 2fr'** indicates three rows, with the first row taking up 1/4 of the parent component's full height, the second row 1/4, and the third row 2/4. 257 258You can use **rowsTemplate('repeat(auto-fill,track-size)')** to automatically calculate the number of rows based on the specified row height **track-size**. **repeat** and **auto-fill** are keywords. The units for **track-size** can be px, vp (default), %, or a valid number. 259 260**Atomic service API**: This API can be used in atomic services since API version 11. 261 262**System capability**: SystemCapability.ArkUI.ArkUI.Full 263 264**Parameters** 265 266| Name| Type | Mandatory| Description | 267| ------ | ------ | ---- | ---------------------------------------------- | 268| value | string | Yes | Number of rows in the layout.<br>Default value: **'1fr'**| 269 270### itemConstraintSize 271 272itemConstraintSize(value: ConstraintSizeOptions) 273 274Sets the size constraints of the child components during layout. 275 276**Atomic service API**: This API can be used in atomic services since API version 11. 277 278**System capability**: SystemCapability.ArkUI.ArkUI.Full 279 280**Parameters** 281 282| Name| Type | Mandatory| Description | 283| ------ | ---------------------------------------------------------- | ---- | ---------- | 284| value | [ConstraintSizeOptions](ts-types.md#constraintsizeoptions) | Yes | Size constraints of the child components during layout. If the value specified is less than 0, this parameter does not take effect.<br>**NOTE**<br>1. If both **itemConstraintSize** and the [constraintSize](ts-universal-attributes-size.md#constraintsize) attribute of the **FlowItem** are set, the **minWidth** (or **minHeight**) will be the larger of the two values, and the **maxWidth** (or **maxHeight**) will be the smaller of the two values. The resulting values will then be used as the **constraintSize** for the **FlowItem**. 2. When only **itemConstraintSize** is set, it effectively applies a uniform size constraint to all child components in the **WaterFlow**. 3. The **itemConstraintSize** attribute, once converted to the **constraintSize** attribute of the **FlowItem** through the two methods mentioned above, follows the same rules for taking effect as the universal attribute [constraintSize](./ts-universal-attributes-size.md#constraintsize).| 285 286### columnsGap 287 288columnsGap(value: Length) 289 290Sets the gap between columns. 291 292**Atomic service API**: This API can be used in atomic services since API version 11. 293 294**System capability**: SystemCapability.ArkUI.ArkUI.Full 295 296**Parameters** 297 298| Name| Type | Mandatory| Description | 299| ------ | ---------------------------- | ---- | ----------------------------- | 300| value | [Length](ts-types.md#length) | Yes | Gap between columns.<br>Default value: **0**| 301 302### rowsGap 303 304rowsGap(value: Length) 305 306Sets the gap between rows. 307 308**Atomic service API**: This API can be used in atomic services since API version 11. 309 310**System capability**: SystemCapability.ArkUI.ArkUI.Full 311 312**Parameters** 313 314| Name| Type | Mandatory| Description | 315| ------ | ---------------------------- | ---- | ----------------------------- | 316| value | [Length](ts-types.md#length) | Yes | Gap between rows.<br>Default value: **0**| 317 318### layoutDirection 319 320layoutDirection(value: FlexDirection) 321 322Sets the main axis direction of the layout. 323 324**Atomic service API**: This API can be used in atomic services since API version 11. 325 326**System capability**: SystemCapability.ArkUI.ArkUI.Full 327 328**Parameters** 329 330| Name| Type | Mandatory| Description | 331| ------ | --------------------------------------------------- | ---- | ------------------------------------------------- | 332| value | [FlexDirection](ts-appendix-enums.md#flexdirection) | Yes | Main axis direction of the layout.<br>Default value: **FlexDirection.Column**| 333 334The priority of **layoutDirection** is higher than that of **rowsTemplate** and **columnsTemplate**. Depending on the **layoutDirection** settings, there are three layout modes: 335 336- **layoutDirection** is set to **FlexDirection.Column** or **FlexDirection.ColumnReverse** 337 338 In this case, **columnsTemplate** is valid. If it is not set, the default value is used. For example, if **columnsTemplate** is set to **"1fr 1fr"** and **rowsTemplate** **"1fr 1fr 1fr"**, child components are arranged in vertical layout, with the cross axis equally divided into two columns. 339 340- **layoutDirection** set to **FlexDirection.Row** or **FlexDirection.RowReverse** 341 342 In this case, **rowsTemplate** is valid. If it is not set, the default value is used. For example, if **columnsTemplate** is set to **"1fr 1fr"** and **rowsTemplate** **"1fr 1fr 1fr"**, child components are arranged in horizontal layout, with the cross axis equally divided into three columns. 343 344- **layoutDirection** is not set 345 346 In this case, the default value of **layoutDirection** is used, which is **FlexDirection.Column**, and **columnsTemplate** is valid. For example, if **columnsTemplate** is set to **"1fr 1fr"** and **rowsTemplate** **"1fr 1fr 1fr"**, child components are arranged in vertical layout, with the cross axis equally divided into two columns. 347 348### enableScrollInteraction<sup>10+</sup> 349 350enableScrollInteraction(value: boolean) 351 352Sets whether to support scroll gestures. When this attribute is set to **false**, scrolling by finger or mouse is not supported, but the scrolling controller API is not affected. 353 354**Atomic service API**: This API can be used in atomic services since API version 11. 355 356**System capability**: SystemCapability.ArkUI.ArkUI.Full 357 358**Parameters** 359 360| Name| Type | Mandatory| Description | 361| ------ | ------- | ---- | ----------------------------------- | 362| value | boolean | Yes | Whether to support scroll gestures.<br>Default value: **true**| 363 364### nestedScroll<sup>10+</sup> 365 366nestedScroll(value: NestedScrollOptions) 367 368Sets the nested scrolling mode in the forward and backward directions to implement scrolling linkage with the parent component. 369 370**Atomic service API**: This API can be used in atomic services since API version 11. 371 372**System capability**: SystemCapability.ArkUI.ArkUI.Full 373 374**Parameters** 375 376| Name| Type | Mandatory| Description | 377| ------ | ------------------------------------------------------------ | ---- | -------------- | 378| value | [NestedScrollOptions](ts-container-scrollable-common.md#nestedscrolloptions10) | Yes | Nested scrolling options.| 379 380### friction<sup>10+</sup> 381 382friction(value: number | Resource) 383 384Sets the friction coefficient. It applies only to gestures in the scrolling area, and it affects only indirectly the scroll chaining during the inertial scrolling process. If this attribute is set to a value less than or equal to 0, the default value is used. 385 386**Atomic service API**: This API can be used in atomic services since API version 11. 387 388**System capability**: SystemCapability.ArkUI.ArkUI.Full 389 390**Parameters** 391 392| Name| Type | Mandatory| Description | 393| ------ | ---------------------------------------------------- | ---- | --------------------------------------------------------- | 394| value | number \| [Resource](ts-types.md#resource) | Yes | Friction coefficient.<br>Default value: **0.9** for wearable devices and **0.6** for non-wearable devices.<br>Since API version 11, the default value for non-wearable devices is **0.7**.<br>Since API version 12, the default value for non-wearable devices is **0.75**.| 395 396### cachedCount<sup>11+</sup> 397 398cachedCount(value: number) 399 400Sets the number of items to be cached. This attribute is effective only in [LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md). After this attribute is set, items that exceed the display and cache range are released. A value less than 0 evaluates to the default value. 401 402**Atomic service API**: This API can be used in atomic services since API version 12. 403 404**System capability**: SystemCapability.ArkUI.ArkUI.Full 405 406**Parameters** 407 408| Name| Type | Mandatory| Description | 409| ------ | ------ | ---- | ------------------------------------------------------------ | 410| value | number | Yes | Number of water flow items to be preloaded (cached).<br>Default value: number of nodes visible on the screen, with the maximum value of 16| 411 412### cachedCount<sup>14+</sup> 413 414cachedCount(count: number, show: boolean) 415 416Sets the number of water flow items to be cached (preloaded) and specifies whether to display the cached nodes. 417 418When this attribute is used in conjunction with the [clip](ts-universal-attributes-sharp-clipping.md#clip12) or [content clipping](ts-container-scrollable-common.md#clipcontent14) attributes, the cached nodes can be displayed. 419 420In [LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md) and [Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md) with the **virtualScroll** option enabled, water flow items that are outside the display and cache range will be released. 421 422**Atomic service API**: This API can be used in atomic services since API version 14. 423 424**System capability**: SystemCapability.ArkUI.ArkUI.Full 425 426**Parameters** 427 428| Name| Type | Mandatory| Description | 429| ------ | ------ | ---- | ---------------------------------------- | 430| count | number | Yes | Number of water flow items to be preloaded (cached).<br>Default value: number of nodes visible on the screen, with the maximum value of 16| 431| show | boolean | Yes | Whether to display the cached water flow items.<br> Default value: **false**| 432 433## Events 434 435In addition to [universal events](ts-component-general-events.md) and [scrollable component common events](ts-container-scrollable-common.md#events), the following events are also supported. 436 437### onReachStart 438 439onReachStart(event: () => void) 440 441Triggered when the component reaches the start. 442 443**Atomic service API**: This API can be used in atomic services since API version 11. 444 445**System capability**: SystemCapability.ArkUI.ArkUI.Full 446 447### onReachEnd 448 449onReachEnd(event: () => void) 450 451Triggered when the component reaches the end position. 452 453**Atomic service API**: This API can be used in atomic services since API version 11. 454 455**System capability**: SystemCapability.ArkUI.ArkUI.Full 456 457### onScrollFrameBegin<sup>10+</sup> 458 459onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number; }) 460 461Triggered when the component starts to scroll. The input parameters indicate the amount by which the component will scroll. The event handler then works out the amount by which the component needs to scroll based on the real-world situation and returns the result. 462 463This event is triggered when the user starts dragging the component or the component starts inertial scrolling. It is not triggered when the component rebounds, the scrolling controller is used, or the scrollbar is dragged. 464 465**Atomic service API**: This API can be used in atomic services since API version 11. 466 467**System capability**: SystemCapability.ArkUI.ArkUI.Full 468 469**Parameters** 470 471| Name| Type | Mandatory| Description | 472| ------ | ------------------------------------------------------- | ---- | -------------------------- | 473| offset | number | Yes | Amount to scroll by, in vp.| 474| state | [ScrollState](ts-container-list.md#scrollstate) | Yes | Current scroll state. | 475 476**Return value** 477 478| Type | Description | 479| ------------------------ | -------------------- | 480| { offsetRemain: number } | Actual amount by which the component scrolls, in vp.| 481 482### onScrollIndex<sup>11+</sup> 483 484onScrollIndex(event: (first: number, last: number) => void) 485 486Triggered when the first or last item displayed in the component changes. It is triggered once when the component is initialized. 487 488This event is triggered when either of the preceding indexes changes. 489 490**Atomic service API**: This API can be used in atomic services since API version 11. 491 492**System capability**: SystemCapability.ArkUI.ArkUI.Full 493 494**Parameters** 495 496| Name| Type | Mandatory| Description | 497| ------ | ------ | ---- | ------------------------------------- | 498| first | number | Yes | Index of the first item of the component.| 499| last | number | Yes | Index of the last item of the component. | 500 501## Example 502 503### Example 1: Using a Basic WaterFlow Component 504This example demonstrates the basic usage of the **WaterFlow** component, including data loading, attribute setting, and event callbacks. 505 506<!--code_no_check--> 507```ts 508// WaterFlowDataSource.ets 509 510// Object that implements the IDataSource API, which is used by the WaterFlow component to load data. 511export class WaterFlowDataSource implements IDataSource { 512 private dataArray: number[] = []; 513 private listeners: DataChangeListener[] = []; 514 515 constructor() { 516 for (let i = 0; i < 100; i++) { 517 this.dataArray.push(i); 518 } 519 } 520 521 // Obtain the data corresponding to the specified index. 522 public getData(index: number): number { 523 return this.dataArray[index]; 524 } 525 526 // Notify the controller of data reloading. 527 notifyDataReload(): void { 528 this.listeners.forEach(listener => { 529 listener.onDataReloaded(); 530 }) 531 } 532 533 // Notify the controller of data addition. 534 notifyDataAdd(index: number): void { 535 this.listeners.forEach(listener => { 536 listener.onDataAdd(index); 537 }) 538 } 539 540 // Notify the controller of data changes. 541 notifyDataChange(index: number): void { 542 this.listeners.forEach(listener => { 543 listener.onDataChange(index); 544 }) 545 } 546 547 // Notify the controller of data deletion. 548 notifyDataDelete(index: number): void { 549 this.listeners.forEach(listener => { 550 listener.onDataDelete(index); 551 }) 552 } 553 554 // Notify the controller of the data location change. 555 notifyDataMove(from: number, to: number): void { 556 this.listeners.forEach(listener => { 557 listener.onDataMove(from, to); 558 }) 559 } 560 561 // Notify the controller of batch data modification. 562 notifyDatasetChange(operations: DataOperation[]): void { 563 this.listeners.forEach(listener => { 564 listener.onDatasetChange(operations); 565 }) 566 } 567 568 // Obtain the total number of data records. 569 public totalCount(): number { 570 return this.dataArray.length; 571 } 572 573 // Register the data change listener. 574 registerDataChangeListener(listener: DataChangeListener): void { 575 if (this.listeners.indexOf(listener) < 0) { 576 this.listeners.push(listener); 577 } 578 } 579 580 // Unregister the data change listener. 581 unregisterDataChangeListener(listener: DataChangeListener): void { 582 const pos = this.listeners.indexOf(listener); 583 if (pos >= 0) { 584 this.listeners.splice(pos, 1); 585 } 586 } 587 588 // Add data. 589 public add1stItem(): void { 590 this.dataArray.splice(0, 0, this.dataArray.length); 591 this.notifyDataAdd(0); 592 } 593 594 // Add an item to the end of the data. 595 public addLastItem(): void { 596 this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length); 597 this.notifyDataAdd(this.dataArray.length - 1); 598 } 599 600 // Add an item to the position corresponding to the specified index. 601 public addItem(index: number): void { 602 this.dataArray.splice(index, 0, this.dataArray.length); 603 this.notifyDataAdd(index); 604 } 605 606 // Delete the first item. 607 public delete1stItem(): void { 608 this.dataArray.splice(0, 1); 609 this.notifyDataDelete(0); 610 } 611 612 // Delete the second item. 613 public delete2ndItem(): void { 614 this.dataArray.splice(1, 1); 615 this.notifyDataDelete(1); 616 } 617 618 // Delete the last item. 619 public deleteLastItem(): void { 620 this.dataArray.splice(-1, 1); 621 this.notifyDataDelete(this.dataArray.length); 622 } 623 624 // Delete an item at the specified index position. 625 public deleteItem(index: number): void { 626 this.dataArray.splice(index, 1); 627 this.notifyDataDelete(index); 628 } 629 630 // Reload data. 631 public reload(): void { 632 this.dataArray.splice(1, 1); 633 this.dataArray.splice(3, 2); 634 this.notifyDataReload(); 635 } 636} 637``` 638 639<!--code_no_check--> 640```ts 641// Index.ets 642import { WaterFlowDataSource } from './WaterFlowDataSource'; 643 644@Entry 645@Component 646struct WaterFlowDemo { 647 @State minSize: number = 80; 648 @State maxSize: number = 180; 649 @State fontSize: number = 24; 650 @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; 651 scroller: Scroller = new Scroller(); 652 dataSource: WaterFlowDataSource = new WaterFlowDataSource(); 653 private itemWidthArray: number[] = []; 654 private itemHeightArray: number[] = []; 655 656 // Calculate the width and height of a water flow item. 657 getSize() { 658 let ret = Math.floor(Math.random() * this.maxSize); 659 return (ret > this.minSize ? ret : this.minSize); 660 } 661 662 // Set the width and height array of the water flow item. 663 setItemSizeArray() { 664 for (let i = 0; i < 100; i++) { 665 this.itemWidthArray.push(this.getSize()); 666 this.itemHeightArray.push(this.getSize()); 667 } 668 } 669 670 aboutToAppear() { 671 this.setItemSizeArray(); 672 } 673 674 @Builder 675 itemFoot() { 676 Column() { 677 Text(`Footer`) 678 .fontSize(10) 679 .backgroundColor(Color.Red) 680 .width(50) 681 .height(50) 682 .align(Alignment.Center) 683 .margin({ top: 2 }) 684 } 685 } 686 687 build() { 688 Column({ space: 2 }) { 689 WaterFlow() { 690 LazyForEach(this.dataSource, (item: number) => { 691 FlowItem() { 692 Column() { 693 Text("N" + item).fontSize(12).height('16') 694 // The image is displayed only when there is a corresponding JPG file. 695 Image('res/waterFlowTest(' + item % 5 + ').jpg') 696 .objectFit(ImageFit.Fill) 697 .width('100%') 698 .layoutWeight(1) 699 } 700 } 701 .onAppear(() => { 702 // Add data in advance when scrolling is about to end. 703 if (item + 20 == this.dataSource.totalCount()) { 704 for (let i = 0; i < 100; i++) { 705 this.dataSource.addLastItem(); 706 } 707 } 708 }) 709 .width('100%') 710 .height(this.itemHeightArray[item % 100]) 711 .backgroundColor(this.colors[item % 5]) 712 }, (item: string) => item) 713 } 714 .columnsTemplate("1fr 1fr") 715 .columnsGap(10) 716 .rowsGap(5) 717 .backgroundColor(0xFAEEE0) 718 .width('100%') 719 .height('100%') 720 .onReachStart(() => { 721 console.info('waterFlow reach start'); 722 }) 723 .onScrollStart(() => { 724 console.info('waterFlow scroll start'); 725 }) 726 .onScrollStop(() => { 727 console.info('waterFlow scroll stop'); 728 }) 729 .onScrollFrameBegin((offset: number, state: ScrollState) => { 730 console.info('waterFlow scrollFrameBegin offset: ' + offset + ' state: ' + state.toString()); 731 return { offsetRemain: offset }; 732 }) 733 } 734 } 735} 736``` 737 738 739 740### Example 2: Implementing Automatic Column Count Calculation 741This example showcases how to implement automatic column count calculation using the **auto-fill** feature. 742 743<!--code_no_check--> 744```ts 745// Index.ets 746import { WaterFlowDataSource } from './WaterFlowDataSource'; 747 748@Entry 749@Component 750struct WaterFlowDemo { 751 @State minSize: number = 80; 752 @State maxSize: number = 180; 753 @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; 754 dataSource: WaterFlowDataSource = new WaterFlowDataSource(); 755 private itemWidthArray: number[] = []; 756 private itemHeightArray: number[] = []; 757 758 // Calculate the width and height of a water flow item. 759 getSize() { 760 let ret = Math.floor(Math.random() * this.maxSize); 761 return (ret > this.minSize ? ret : this.minSize); 762 } 763 764 // Set the width and height array of the water flow item. 765 setItemSizeArray() { 766 for (let i = 0; i < 100; i++) { 767 this.itemWidthArray.push(this.getSize()); 768 this.itemHeightArray.push(this.getSize()); 769 } 770 } 771 772 aboutToAppear() { 773 this.setItemSizeArray(); 774 } 775 776 build() { 777 Column({ space: 2 }) { 778 WaterFlow() { 779 LazyForEach(this.dataSource, (item: number) => { 780 FlowItem() { 781 Column() { 782 Text("N" + item).fontSize(12).height('16') 783 Image('res/waterFlowTest(' + item % 5 + ').jpg') 784 } 785 } 786 .width('100%') 787 .height(this.itemHeightArray[item % 100]) 788 .backgroundColor(this.colors[item % 5]) 789 }, (item: string) => item) 790 } 791 .columnsTemplate('repeat(auto-fill,80)') 792 .columnsGap(10) 793 .rowsGap(5) 794 .padding({left:5}) 795 .backgroundColor(0xFAEEE0) 796 .width('100%') 797 .height('100%') 798 } 799 } 800} 801``` 802 803 804 805 806### Example 3: Using WaterFlowSections 807This example illustrates the initialization of **WaterFlowSections** and the different effects of various APIs such as **splice**, **push**, **update**, **values**, and **length**. 808For details about how to use these features in conjunction with state management V2, see [WaterFlow](../../../quick-start/arkts-v1-v2-migration.md#waterflow). 809 810<!--code_no_check--> 811```ts 812// Index.ets 813import { WaterFlowDataSource } from './WaterFlowDataSource'; 814 815@Reusable 816@Component 817struct ReusableFlowItem { 818 @State item: number = 0; 819 820 // Invoked when a reusable custom component is re-added to the component tree from the reuse cache. The component state variable can be updated here to display the correct content. 821 aboutToReuse(params: Record<string, number>) { 822 this.item = params.item; 823 console.info('Reuse item:' + this.item); 824 } 825 826 aboutToAppear() { 827 console.info('new item:' + this.item); 828 } 829 830 build() { 831 Image('res/waterFlowTest(' + this.item % 5 + ').jpg') 832 .overlay('N' + this.item, { align: Alignment.Top }) 833 .objectFit(ImageFit.Fill) 834 .width('100%') 835 .layoutWeight(1) 836 } 837} 838 839@Entry 840@Component 841struct WaterFlowDemo { 842 minSize: number = 80; 843 maxSize: number = 180; 844 fontSize: number = 24; 845 colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; 846 scroller: Scroller = new Scroller(); 847 dataSource: WaterFlowDataSource = new WaterFlowDataSource(); 848 dataCount: number = this.dataSource.totalCount(); 849 private itemHeightArray: number[] = []; 850 @State sections: WaterFlowSections = new WaterFlowSections(); 851 sectionMargin: Margin = { top: 10, left: 5, bottom: 10, right: 5 }; 852 oneColumnSection: SectionOptions = { 853 itemsCount: 4, 854 crossCount: 1, 855 columnsGap: '5vp', 856 rowsGap: 10, 857 margin: this.sectionMargin, 858 onGetItemMainSizeByIndex: (index: number) => { 859 return this.itemHeightArray[index % 100]; 860 } 861 } 862 twoColumnSection: SectionOptions = { 863 itemsCount: 2, 864 crossCount: 2, 865 onGetItemMainSizeByIndex: (index: number) => { 866 return 100; 867 } 868 } 869 lastSection: SectionOptions = { 870 itemsCount: 20, 871 crossCount: 2, 872 onGetItemMainSizeByIndex: (index: number) => { 873 return this.itemHeightArray[index % 100]; 874 } 875 } 876 877 // Calculate the FlowItem height. 878 getSize() { 879 let ret = Math.floor(Math.random() * this.maxSize); 880 return (ret > this.minSize ? ret : this.minSize); 881 } 882 883 // Set the height array for FlowItems. 884 setItemSizeArray() { 885 for (let i = 0; i < 100; i++) { 886 this.itemHeightArray.push(this.getSize()); 887 } 888 } 889 890 aboutToAppear() { 891 this.setItemSizeArray(); 892 // Initialize the water flow section information. 893 let sectionOptions: SectionOptions[] = []; 894 let count = 0; 895 let oneOrTwo = 0; 896 while (count < this.dataCount) { 897 if (this.dataCount - count < 20) { 898 this.lastSection.itemsCount = this.dataCount - count; 899 sectionOptions.push(this.lastSection); 900 break; 901 } 902 if (oneOrTwo++ % 2 == 0) { 903 sectionOptions.push(this.oneColumnSection); 904 count += this.oneColumnSection.itemsCount; 905 } else { 906 sectionOptions.push(this.twoColumnSection); 907 count += this.twoColumnSection.itemsCount; 908 } 909 } 910 this.sections.splice(0, 0, sectionOptions); 911 } 912 913 build() { 914 Column({ space: 2 }) { 915 Row() { 916 Button('splice') 917 .height('5%') 918 .onClick(() => { 919 // Replace all sections with a new section. Ensure that the number of data array items in LazyForEach is the same as the value of itemsCount of the new section. 920 let totalCount: number = this.dataSource.totalCount(); 921 let newSection: SectionOptions = { 922 itemsCount: totalCount, 923 crossCount: 2, 924 onGetItemMainSizeByIndex: (index: number) => { 925 return this.itemHeightArray[index % 100]; 926 } 927 } 928 let oldLength: number = this.sections.length(); 929 this.sections.splice(0, oldLength, [newSection]); 930 }) 931 .margin({ top: 10, left: 20 }) 932 Button('update') 933 .height('5%') 934 .onClick(() => { 935 // Add four FlowItems to the second section. Ensure that the number of data array items in LazyForEach is the same as the sum of itemsCount values of all sections. 936 let newSection: SectionOptions = { 937 itemsCount: 6, 938 crossCount: 3, 939 columnsGap: 5, 940 rowsGap: 10, 941 margin: this.sectionMargin, 942 onGetItemMainSizeByIndex: (index: number) => { 943 return this.itemHeightArray[index % 100]; 944 } 945 } 946 this.dataSource.addItem(this.oneColumnSection.itemsCount); 947 this.dataSource.addItem(this.oneColumnSection.itemsCount + 1); 948 this.dataSource.addItem(this.oneColumnSection.itemsCount + 2); 949 this.dataSource.addItem(this.oneColumnSection.itemsCount + 3); 950 const result: boolean = this.sections.update(1, newSection); 951 console.info('update:' + result); 952 }) 953 .margin({ top: 10, left: 20 }) 954 Button('delete') 955 .height('5%') 956 .onClick(() => { 957 // Click Update and then Delete. 958 let newSection: SectionOptions = { 959 itemsCount: 2, 960 crossCount: 2, 961 columnsGap: 5, 962 rowsGap: 10, 963 margin: this.sectionMargin, 964 onGetItemMainSizeByIndex: (index: number) => { 965 return this.itemHeightArray[index % 100]; 966 } 967 } 968 this.dataSource.deleteItem(this.oneColumnSection.itemsCount); 969 this.dataSource.deleteItem(this.oneColumnSection.itemsCount); 970 this.dataSource.deleteItem(this.oneColumnSection.itemsCount); 971 this.dataSource.deleteItem(this.oneColumnSection.itemsCount); 972 this.sections.update(1, newSection); 973 }) 974 .margin({ top: 10, left: 20 }) 975 Button('values') 976 .height('5%') 977 .onClick(() => { 978 const sections: Array<SectionOptions> = this.sections.values(); 979 for (const value of sections) { 980 console.log(JSON.stringify(value)); 981 } 982 console.info('count:' + this.sections.length()); 983 }) 984 .margin({ top: 10, left: 20 }) 985 }.margin({ bottom: 20 }) 986 987 WaterFlow({ scroller: this.scroller, sections: this.sections }) { 988 LazyForEach(this.dataSource, (item: number) => { 989 FlowItem() { 990 ReusableFlowItem({ item: item }) 991 } 992 .width('100%') 993 // The value of onGetItemMainSizeByIndex is used. 994 // .height(this.itemHeightArray[item % 100]) 995 .backgroundColor(this.colors[item % 5]) 996 }, (item: string) => item) 997 } 998 .columnsTemplate('1fr 1fr') // This attribute is ineffective when the sections parameter is used. 999 .columnsGap(10) 1000 .rowsGap(5) 1001 .backgroundColor(0xFAEEE0) 1002 .width('100%') 1003 .height('100%') 1004 .layoutWeight(1) 1005 .onScrollIndex((first: number, last: number) => { 1006 // Add data in advance when scrolling is about to end. 1007 if (last + 20 >= this.dataSource.totalCount()) { 1008 for (let i = 0; i < 100; i++) { 1009 this.dataSource.addLastItem(); 1010 } 1011 // After the data source is updated, update sections synchronously and change the number of FlowItems in the last section. 1012 const sections: Array<SectionOptions> = this.sections.values(); 1013 let newSection: SectionOptions = sections[this.sections.length() - 1]; 1014 newSection.itemsCount += 100; 1015 this.sections.update(-1, newSection); 1016 } 1017 }) 1018 } 1019 } 1020} 1021``` 1022 1023 1024 1025### Example 4: Using the Pinch Gesture to Change the Column Count 1026This example demonstrates how to use [priorityGesture](ts-gesture-settings.md) and [PinchGesture](ts-basic-gestures-pinchgesture.md) to implement the feature of using a pinch gesture to change the number of columns in a layout. 1027 1028<!--code_no_check--> 1029```ts 1030// Index.ets 1031import { WaterFlowDataSource } from './WaterFlowDataSource'; 1032 1033@Reusable 1034@Component 1035struct ReusableFlowItem { 1036 @State item: number = 0; 1037 1038 // Invoked when a reusable custom component is re-added to the component tree from the reuse cache. The component state variable can be updated here to display the correct content. 1039 aboutToReuse(params: Record<string, number>) { 1040 this.item = params.item; 1041 console.info('Reuse item:' + this.item); 1042 } 1043 1044 aboutToAppear() { 1045 console.info('item:' + this.item); 1046 } 1047 1048 build() { 1049 Column() { 1050 Text("N" + this.item).fontSize(12).height('16') 1051 Image('res/waterFlow (' + this.item % 5 + ').JPG') 1052 .objectFit(ImageFit.Fill) 1053 .width('100%') 1054 .layoutWeight(1) 1055 } 1056 } 1057} 1058 1059@Entry 1060@Component 1061struct WaterFlowDemo { 1062 minSize: number = 80; 1063 maxSize: number = 180; 1064 colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; 1065 @State columns: number = 2; 1066 dataSource: WaterFlowDataSource = new WaterFlowDataSource(); 1067 private itemWidthArray: number[] = []; 1068 private itemHeightArray: number[] = []; 1069 1070 // Calculate the width and height of a water flow item. 1071 getSize() { 1072 let ret = Math.floor(Math.random() * this.maxSize); 1073 return (ret > this.minSize ? ret : this.minSize); 1074 } 1075 1076 // Set the width and height array of the water flow item. 1077 setItemSizeArray() { 1078 for (let i = 0; i < 100; i++) { 1079 this.itemWidthArray.push(this.getSize()); 1080 this.itemHeightArray.push(this.getSize()); 1081 } 1082 } 1083 1084 aboutToAppear() { 1085 let lastCount = AppStorage.get<number>('columnsCount'); 1086 if (typeof lastCount != 'undefined') { 1087 this.columns = lastCount; 1088 } 1089 this.setItemSizeArray(); 1090 } 1091 1092 build() { 1093 Column({ space: 2 }) { 1094 Row() { 1095 Text('Pinch to change the number of columns') 1096 .height('5%') 1097 .margin({ top: 10, left: 20 }) 1098 } 1099 1100 WaterFlow() { 1101 LazyForEach(this.dataSource, (item: number) => { 1102 FlowItem() { 1103 ReusableFlowItem({ item: item }) 1104 } 1105 .width('100%') 1106 .height(this.itemHeightArray[item % 100]) 1107 .backgroundColor(this.colors[item % 5]) 1108 }, (item: string) => item) 1109 } 1110 .columnsTemplate('1fr '.repeat(this.columns)) 1111 .columnsGap(10) 1112 .rowsGap(5) 1113 .backgroundColor(0xFAEEE0) 1114 .width('100%') 1115 .height('100%') 1116 .layoutWeight(1) 1117 // Switching the number of columns triggers a reordering animation for the item positions. 1118 .animation({ 1119 duration: 300, 1120 curve: Curve.Smooth 1121 }) 1122 .priorityGesture( 1123 PinchGesture() 1124 .onActionEnd((event: GestureEvent) => { 1125 console.info('end scale:' + event.scale); 1126 // When a user performs a pinch-to-zoom gesture by moving their fingers apart, and the number of columns decreases to a certain threshold (in this case, 2), it will cause the items to enlarge. 1127 if (event.scale > 2) { 1128 this.columns--; 1129 } else if (event.scale < 0.6) { 1130 this.columns++; 1131 } 1132 // You can set the maximum and minimum number of columns based on the device screen width. Here, the minimum number of columns is 1, and the maximum number of columns is 4. 1133 this.columns = Math.min(4, Math.max(1, this.columns)); 1134 AppStorage.setOrCreate<number>('columnsCount', this.columns); 1135 }) 1136 ) 1137 } 1138 } 1139} 1140``` 1141 1142 1143 1144### Example 5: Setting the Edge Fading Effect 1145This example demonstrates how to enable the edge fading effect for the **WaterFlow** component using the [fadingEdge](ts-container-scrollable-common.md#fadingedge14) API and set the length of the fading edge using the **fadingEdgeLength** parameter. 1146 1147<!--code_no_check--> 1148```ts 1149// Index.ets 1150import { LengthMetrics } from '@kit.ArkUI'; 1151import { WaterFlowDataSource } from './WaterFlowDataSource'; 1152@Entry 1153@Component 1154struct WaterFlowDemo { 1155 @State minSize: number = 80; 1156 @State maxSize: number = 180; 1157 @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]; 1158 dataSource: WaterFlowDataSource = new WaterFlowDataSource(); 1159 scroller: Scroller = new Scroller(); 1160 private itemWidthArray: number[] = []; 1161 private itemHeightArray: number[] = []; 1162 1163 // Calculate the width and height of a water flow item. 1164 getSize() { 1165 let ret = Math.floor(Math.random() * this.maxSize); 1166 return (ret > this.minSize ? ret : this.minSize); 1167 } 1168 1169 // Set the width and height array of the water flow item. 1170 setItemSizeArray() { 1171 for (let i = 0; i < 100; i++) { 1172 this.itemWidthArray.push(this.getSize()); 1173 this.itemHeightArray.push(this.getSize()); 1174 } 1175 } 1176 1177 aboutToAppear() { 1178 this.setItemSizeArray(); 1179 } 1180 1181 build() { 1182 Column({ space: 2 }) { 1183 1184 WaterFlow({ scroller:this.scroller }) { 1185 LazyForEach(this.dataSource, (item: number) => { 1186 FlowItem() { 1187 Column() { 1188 Text("N" + item).fontSize(12).height('16') 1189 } 1190 } 1191 .width('100%') 1192 .height(this.itemHeightArray[item % 100]) 1193 .backgroundColor(this.colors[item % 5]) 1194 }, (item: string) => item) 1195 } 1196 .columnsTemplate('repeat(auto-fill,80)') 1197 .columnsGap(10) 1198 .rowsGap(5) 1199 .height('90%') 1200 .scrollBar(BarState.On) 1201 .fadingEdge(true,{fadingEdgeLength:LengthMetrics.vp(80)}) 1202 1203 } 1204 } 1205} 1206``` 1207 1208 1209