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 25**Atomic service API**: This API can be used in atomic services since API version 11. 26 27**System capability**: SystemCapability.ArkUI.ArkUI.Full 28 29**Parameters** 30 31| Name| Type| Mandatory| Description| 32| -------- | -------- | -------- | -------- | 33| options | [WaterFlowOptions](#waterflowoptions)| No| Parameters of the **WaterFlow** component.| 34 35 36## WaterFlowOptions 37 38**System capability**: SystemCapability.ArkUI.ArkUI.Full 39 40| Name | Type | Mandatory| Description | 41| ---------- | ----------------------------------------------- | ------ | -------------------------------------------- | 42| 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.| 43| 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.| 44| 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. | 45| 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. 46 47 48## WaterFlowSections<sup>12+</sup> 49 50Describes the water flow item sections. 51 52> **NOTE** 53> 54> 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. 55 56### constructor 57 58constructor() 59 60A constructor used to create a **WaterFlowSections** object. 61 62**Atomic service API**: This API can be used in atomic services since API version 12. 63 64**System capability**: SystemCapability.ArkUI.ArkUI.Full 65 66### splice<sup>12+</sup> 67 68splice(start: number, deleteCount?: number, sections?: Array\<SectionOptions\>): boolean 69 70Changes sections by removing or replacing an existing section and/or adding a section. 71 72**Atomic service API**: This API can be used in atomic services since API version 12. 73 74**System capability**: SystemCapability.ArkUI.ArkUI.Full 75 76**Parameters** 77 78| Name | Type | Mandatory | Description | 79| ---- | ----------------------------- | ---- | -------------------- | 80| 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.| 81| 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.| 82| 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.| 83 84**Return value** 85 86| Type | Description | 87| ------------------------------------------------------------ | ------------------------------------------------------------ | 88| boolean | Whether the changing is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 89 90 91### push<sup>12+</sup> 92 93push(section: SectionOptions): boolean 94 95Adds the specified sections to the end of the **WaterFlow** component. 96 97**Atomic service API**: This API can be used in atomic services since API version 12. 98 99**System capability**: SystemCapability.ArkUI.ArkUI.Full 100 101**Parameters** 102 103| Name | Type | Mandatory | Description | 104| ---- | ----------------------------- | ---- | -------------------- | 105| section | [SectionOptions](#sectionoptions12) | Yes | Sections to add to the end of the **WaterFlow** component.| 106 107**Return value** 108 109| Type | Description | 110| ------------------------------------------------------------ | ------------------------------------------------------------ | 111| boolean | Whether the adding is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 112 113### update<sup>12+</sup> 114 115update(sectionIndex: number, section: SectionOptions): boolean 116 117Updates the configuration of a specified water flow item section. 118 119**Atomic service API**: This API can be used in atomic services since API version 12. 120 121**System capability**: SystemCapability.ArkUI.ArkUI.Full 122 123**Parameters** 124 125| Name | Type | Mandatory | Description | 126| ---- | ----------------------------- | ---- | -------------------- | 127| 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.| 128| section | [SectionOptions](#sectionoptions12) | Yes | New section configuration.| 129 130**Return value** 131 132| Type | Description | 133| ------------------------------------------------------------ | ------------------------------------------------------------ | 134| boolean | Whether the update is successful. If the value of **itemsCount** in any section to add is not a positive integer, **false** is returned.| 135 136### values<sup>12+</sup> 137 138values(): Array\<SectionOptions\> 139 140Obtains the configuration of all sections in the **WaterFlow** component. 141 142**Atomic service API**: This API can be used in atomic services since API version 12. 143 144**System capability**: SystemCapability.ArkUI.ArkUI.Full 145 146**Return value** 147 148| Type | Description | 149| ------------------------------------------------------------ | ------------------------------------------------------------ | 150| Array<[SectionOptions](#sectionoptions12)> | Configuration of all sections in the **WaterFlow** component.| 151 152### length<sup>12+</sup> 153 154length(): number 155 156Obtains the number of sections in the **WaterFlow** component. 157 158**Atomic service API**: This API can be used in atomic services since API version 12. 159 160**System capability**: SystemCapability.ArkUI.ArkUI.Full 161 162**Return value** 163 164| Type | Description | 165| ------------------------------------------------------------ | ------------------------------------------------------------ | 166| number | Number of sections in the **WaterFlow** component.| 167 168## SectionOptions<sup>12+</sup> 169 170Describes the configuration of the water flow item section. 171 172**Atomic service API**: This API can be used in atomic services since API version 12. 173 174**System capability**: SystemCapability.ArkUI.ArkUI.Full 175 176| Name| Type| Mandatory| Description| 177|------|-----|-----|-----| 178| 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.| 179| 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.| 180| 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.| 181| 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.| 182| 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.| 183| 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.| 184 185 186## GetItemMainSizeByIndex<sup>12+</sup> 187 188type GetItemMainSizeByIndex = (index: number) => number 189 190Obtains the main axis size of a specified water flow item based on its index. 191 192**Atomic service API**: This API can be used in atomic services since API version 12. 193 194**System capability**: SystemCapability.ArkUI.ArkUI.Full 195 196**Parameters** 197 198| Name | Type | Mandatory | Description | 199| ---- | ----------------------------- | ---- | -------------------- | 200| index | number | Yes | Index of the target water flow item.| 201 202**Return value** 203 204| Type | Description | 205| ------------------------------------------------------------ | ------------------------------------------------------------ | 206| 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.| 207 208## WaterFlowLayoutMode<sup>12+</sup> 209 210**Atomic service API**: This API can be used in atomic services since API version 12. 211 212**System capability**: SystemCapability.ArkUI.ArkUI.Full 213 214| Name| Value| Description| 215| ------ | ------ | -------------------- | 216| 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.| 217| 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.| 218 219 220## Attributes 221 222In addition to [universal attributes](ts-universal-attributes-size.md) and [scrollable component common attributes](ts-container-scrollable-common.md#attributes), the following attributes are also supported. 223 224### columnsTemplate 225 226columnsTemplate(value: string) 227 228Sets the number of columns in the layout. If this attribute is not set, one column is used by default. 229 230For 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. 231 232You 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. 233 234**Atomic service API**: This API can be used in atomic services since API version 11. 235 236**System capability**: SystemCapability.ArkUI.ArkUI.Full 237 238**Parameters** 239 240| Name| Type | Mandatory| Description | 241| ------ | ------ | ---- | ---------------------------------------------- | 242| value | string | Yes | Number of columns in the layout.<br>Default value: **'1fr'**| 243 244### rowsTemplate 245 246rowsTemplate(value: string) 247 248Sets the number of rows in the layout. If this attribute is not set, one row is used by default. 249 250For 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. 251 252You 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. 253 254**Atomic service API**: This API can be used in atomic services since API version 11. 255 256**System capability**: SystemCapability.ArkUI.ArkUI.Full 257 258**Parameters** 259 260| Name| Type | Mandatory| Description | 261| ------ | ------ | ---- | ---------------------------------------------- | 262| value | string | Yes | Number of rows in the layout.<br>Default value: **'1fr'**| 263 264### itemConstraintSize 265 266itemConstraintSize(value: ConstraintSizeOptions) 267 268Sets the size constraints of the child components during layout. 269 270**Atomic service API**: This API can be used in atomic services since API version 11. 271 272**System capability**: SystemCapability.ArkUI.ArkUI.Full 273 274**Parameters** 275 276| Name| Type | Mandatory| Description | 277| ------ | ---------------------------------------------------------- | ---- | ---------- | 278| 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).| 279 280### columnsGap 281 282columnsGap(value: Length) 283 284Sets the gap between columns. 285 286**Atomic service API**: This API can be used in atomic services since API version 11. 287 288**System capability**: SystemCapability.ArkUI.ArkUI.Full 289 290**Parameters** 291 292| Name| Type | Mandatory| Description | 293| ------ | ---------------------------- | ---- | ----------------------------- | 294| value | [Length](ts-types.md#length) | Yes | Gap between columns.<br>Default value: **0**| 295 296### rowsGap 297 298rowsGap(value: Length) 299 300Sets the gap between rows. 301 302**Atomic service API**: This API can be used in atomic services since API version 11. 303 304**System capability**: SystemCapability.ArkUI.ArkUI.Full 305 306**Parameters** 307 308| Name| Type | Mandatory| Description | 309| ------ | ---------------------------- | ---- | ----------------------------- | 310| value | [Length](ts-types.md#length) | Yes | Gap between rows.<br>Default value: **0**| 311 312### layoutDirection 313 314layoutDirection(value: FlexDirection) 315 316Sets the main axis direction of the layout. 317 318**Atomic service API**: This API can be used in atomic services since API version 11. 319 320**System capability**: SystemCapability.ArkUI.ArkUI.Full 321 322**Parameters** 323 324| Name| Type | Mandatory| Description | 325| ------ | --------------------------------------------------- | ---- | ------------------------------------------------- | 326| value | [FlexDirection](ts-appendix-enums.md#flexdirection) | Yes | Main axis direction of the layout.<br>Default value: **FlexDirection.Column**| 327 328The priority of **layoutDirection** is higher than that of **rowsTemplate** and **columnsTemplate**. Depending on the **layoutDirection** settings, there are three layout modes: 329 330- **layoutDirection** is set to **FlexDirection.Column** or **FlexDirection.ColumnReverse** 331 332 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. 333 334- **layoutDirection** set to **FlexDirection.Row** or **FlexDirection.RowReverse** 335 336 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. 337 338- **layoutDirection** is not set 339 340 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. 341 342### enableScrollInteraction<sup>10+</sup> 343 344enableScrollInteraction(value: boolean) 345 346Sets 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. 347 348**Atomic service API**: This API can be used in atomic services since API version 11. 349 350**System capability**: SystemCapability.ArkUI.ArkUI.Full 351 352**Parameters** 353 354| Name| Type | Mandatory| Description | 355| ------ | ------- | ---- | ----------------------------------- | 356| value | boolean | Yes | Whether to support scroll gestures.<br>Default value: **true**| 357 358### nestedScroll<sup>10+</sup> 359 360nestedScroll(value: NestedScrollOptions) 361 362Sets the nested scrolling mode in the forward and backward directions to implement scrolling linkage with the parent component. 363 364**Atomic service API**: This API can be used in atomic services since API version 11. 365 366**System capability**: SystemCapability.ArkUI.ArkUI.Full 367 368**Parameters** 369 370| Name| Type | Mandatory| Description | 371| ------ | ------------------------------------------------------------ | ---- | -------------- | 372| value | [NestedScrollOptions](ts-container-scrollable-common.md#nestedscrolloptions10) | Yes | Nested scrolling options.| 373 374### friction<sup>10+</sup> 375 376friction(value: number | Resource) 377 378Sets 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. 379 380**Atomic service API**: This API can be used in atomic services since API version 11. 381 382**System capability**: SystemCapability.ArkUI.ArkUI.Full 383 384**Parameters** 385 386| Name| Type | Mandatory| Description | 387| ------ | ---------------------------------------------------- | ---- | --------------------------------------------------------- | 388| 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**.| 389 390### cachedCount<sup>11+</sup> 391 392cachedCount(value: number) 393 394Sets 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. 395 396**Atomic service API**: This API can be used in atomic services since API version 12. 397 398**System capability**: SystemCapability.ArkUI.ArkUI.Full 399 400**Parameters** 401 402| Name| Type | Mandatory| Description | 403| ------ | ------ | ---- | ---------------------------------------- | 404| value | number | Yes | Number of water flow items to be preloaded (cached).<br> Default value: **1**| 405 406### cachedCount<sup>14+</sup> 407 408cachedCount(value: number, show: boolean) 409 410Sets the number of water flow items to be cached (preloaded) and specifies whether to display the cached nodes. 411 412When 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. 413 414In [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. 415 416**Atomic service API**: This API can be used in atomic services since API version 14. 417 418**System capability**: SystemCapability.ArkUI.ArkUI.Full 419 420**Parameters** 421 422| Name| Type | Mandatory| Description | 423| ------ | ------ | ---- | ---------------------------------------- | 424| value | number | Yes | Number of water flow items to be preloaded (cached).<br> Default value: **1**| 425| show | boolean | Yes | Whether to display the cached water flow items.<br> Default value: **false**| 426 427## Events 428 429In addition to [universal events](ts-universal-events-click.md) and [scrollable component common events](ts-container-scrollable-common.md#events), the following events are also supported. 430 431### onReachStart 432 433onReachStart(event: () => void) 434 435Triggered when the component reaches the start. 436 437**Atomic service API**: This API can be used in atomic services since API version 11. 438 439**System capability**: SystemCapability.ArkUI.ArkUI.Full 440 441### onReachEnd 442 443onReachEnd(event: () => void) 444 445Triggered when the component reaches the end position. 446 447**Atomic service API**: This API can be used in atomic services since API version 11. 448 449**System capability**: SystemCapability.ArkUI.ArkUI.Full 450 451### onScrollFrameBegin<sup>10+</sup> 452 453onScrollFrameBegin(event: (offset: number, state: ScrollState) => { offsetRemain: number; }) 454 455Triggered 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. 456 457This 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. 458 459**Atomic service API**: This API can be used in atomic services since API version 11. 460 461**System capability**: SystemCapability.ArkUI.ArkUI.Full 462 463**Parameters** 464 465| Name| Type | Mandatory| Description | 466| ------ | ------------------------------------------------------- | ---- | -------------------------- | 467| offset | number | Yes | Amount to scroll by, in vp.| 468| state | [ScrollState](ts-container-list.md#scrollstate) | Yes | Current scroll state. | 469 470**Return value** 471 472| Type | Description | 473| ------------------------ | -------------------- | 474| { offsetRemain: number } | Actual amount by which the component scrolls, in vp.| 475 476### onScrollIndex<sup>11+</sup> 477 478onScrollIndex(event: (first: number, last: number) => void) 479 480Triggered when the first or last item displayed in the component changes. It is triggered once when the component is initialized. 481 482This event is triggered when either of the preceding indexes changes. 483 484**Atomic service API**: This API can be used in atomic services since API version 11. 485 486**System capability**: SystemCapability.ArkUI.ArkUI.Full 487 488**Parameters** 489 490| Name| Type | Mandatory| Description | 491| ------ | ------ | ---- | ------------------------------------- | 492| first | number | Yes | Index of the first item of the component.| 493| last | number | Yes | Index of the last item of the component. | 494 495## Example 496 497### Example 1: Using a Basic WaterFlow Component 498This example demonstrates the basic usage of the **WaterFlow** component, including data loading, attribute setting, and event callbacks. 499```ts 500// WaterFlowDataSource.ets 501 502// Object that implements the IDataSource API, which is used by the WaterFlow component to load data. 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 // Obtain the data corresponding to the specified index. 514 public getData(index: number): number { 515 return this.dataArray[index] 516 } 517 518 // Notify the controller of data reloading. 519 notifyDataReload(): void { 520 this.listeners.forEach(listener => { 521 listener.onDataReloaded() 522 }) 523 } 524 525 // Notify the controller of data addition. 526 notifyDataAdd(index: number): void { 527 this.listeners.forEach(listener => { 528 listener.onDataAdd(index) 529 }) 530 } 531 532 // Notify the controller of data changes. 533 notifyDataChange(index: number): void { 534 this.listeners.forEach(listener => { 535 listener.onDataChange(index) 536 }) 537 } 538 539 // Notify the controller of data deletion. 540 notifyDataDelete(index: number): void { 541 this.listeners.forEach(listener => { 542 listener.onDataDelete(index) 543 }) 544 } 545 546 // Notify the controller of the data location change. 547 notifyDataMove(from: number, to: number): void { 548 this.listeners.forEach(listener => { 549 listener.onDataMove(from, to) 550 }) 551 } 552 553 // Notify the controller of batch data modification. 554 notifyDatasetChange(operations: DataOperation[]): void { 555 this.listeners.forEach(listener => { 556 listener.onDatasetChange(operations); 557 }) 558 } 559 560 // Obtain the total number of data records. 561 public totalCount(): number { 562 return this.dataArray.length 563 } 564 565 // Register the data change listener. 566 registerDataChangeListener(listener: DataChangeListener): void { 567 if (this.listeners.indexOf(listener) < 0) { 568 this.listeners.push(listener) 569 } 570 } 571 572 // Unregister the data change listener. 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 // Add data. 581 public add1stItem(): void { 582 this.dataArray.splice(0, 0, this.dataArray.length) 583 this.notifyDataAdd(0) 584 } 585 586 // Add an item to the end of the data. 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 // Add an item to the position corresponding to the specified index. 593 public addItem(index: number): void { 594 this.dataArray.splice(index, 0, this.dataArray.length) 595 this.notifyDataAdd(index) 596 } 597 598 // Delete the first item. 599 public delete1stItem(): void { 600 this.dataArray.splice(0, 1) 601 this.notifyDataDelete(0) 602 } 603 604 // Delete the second item. 605 public delete2ndItem(): void { 606 this.dataArray.splice(1, 1) 607 this.notifyDataDelete(1) 608 } 609 610 // Delete the last item. 611 public deleteLastItem(): void { 612 this.dataArray.splice(-1, 1) 613 this.notifyDataDelete(this.dataArray.length) 614 } 615 616 // Delete an item at the specified index position. 617 public deleteItem(index: number): void { 618 this.dataArray.splice(index, 1) 619 this.notifyDataDelete(index) 620 } 621 622 // Reload data. 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 // Calculate the width and height of a water flow item. 648 getSize() { 649 let ret = Math.floor(Math.random() * this.maxSize) 650 return (ret > this.minSize ? ret : this.minSize) 651 } 652 653 // Set the width and height array of the water flow item. 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 // The image is displayed only when there is a corresponding JPG file. 686 Image('res/waterFlowTest(' + item % 5 + ').jpg') 687 .objectFit(ImageFit.Fill) 688 .width('100%') 689 .layoutWeight(1) 690 } 691 } 692 .onAppear(() => { 693 // Add data in advance when scrolling is about to end. 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 730 731### Example 2: Implementing Automatic Column Count Calculation 732This example showcases how to implement automatic column count calculation using the **auto-fill** feature. 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 // Calculate the width and height of a water flow item. 748 getSize() { 749 let ret = Math.floor(Math.random() * this.maxSize) 750 return (ret > this.minSize ? ret : this.minSize) 751 } 752 753 // Set the width and height array of the water flow item. 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 793 794 795### Example 3: Using WaterFlowSections 796This example illustrates the initialization of **WaterFlowSections** and the different effects of various APIs such as **splice**, **push**, **update**, **values**, and **length**. 797For details about how to use these features in conjunction with state management V2, see [WaterFlow](../../../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 // 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. 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 // Calculate the FlowItem height. 865 getSize() { 866 let ret = Math.floor(Math.random() * this.maxSize) 867 return (ret > this.minSize ? ret : this.minSize) 868 } 869 870 // Set the height array for FlowItems. 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 // Initialize the water flow section information. 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 // 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. 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 // 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. 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 // Click Update and then 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 // The value of onGetItemMainSizeByIndex is used. 981 // .height(this.itemHeightArray[item % 100]) 982 .backgroundColor(this.colors[item % 5]) 983 }, (item: string) => item) 984 } 985 .columnsTemplate('1fr 1fr') // This attribute is ineffective when the sections parameter is used. 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 // Add data in advance when scrolling is about to end. 994 if (last + 20 >= this.dataSource.totalCount()) { 995 for (let i = 0; i < 100; i++) { 996 this.dataSource.addLastItem() 997 } 998 // After the data source is updated, update sections synchronously and change the number of FlowItems in the last section. 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 1011 1012### Example 4: Using the Pinch Gesture to Change the Column Count 1013This 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. 1014```ts 1015// Index.ets 1016import { WaterFlowDataSource } from './WaterFlowDataSource' 1017 1018@Reusable 1019@Component 1020struct ReusableFlowItem { 1021 @State item: number = 0 1022 1023 // 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. 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 // Calculate the width and height of a water flow item. 1056 getSize() { 1057 let ret = Math.floor(Math.random() * this.maxSize) 1058 return (ret > this.minSize ? ret : this.minSize) 1059 } 1060 1061 // Set the width and height array of the water flow item. 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('Pinch to change the number of columns') 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 // Switching the number of columns triggers a reordering animation for the item positions. 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 // 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. 1112 if (event.scale > 2) { 1113 this.columns-- 1114 } else if (event.scale < 0.6) { 1115 this.columns++ 1116 } 1117 // 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. 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 1128 1129### Example 5: Setting the Edge Fading Effect 1130This 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. 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 // Calculate the width and height of a water flow item. 1147 getSize() { 1148 let ret = Math.floor(Math.random() * this.maxSize) 1149 return (ret > this.minSize ? ret : this.minSize) 1150 } 1151 1152 // Set the width and height array of the water flow item. 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 .fadingEdge(true,{fadingEdgeLength:LengthMetrics.vp(80)}) 1184 1185 } 1186 } 1187} 1188``` 1189 1190 1191