# LazyVGridLayout The **LazyVGridLayout** component implements a lazy-loading grid layout, with its parent component restricted to [WaterFlow](ts-container-waterflow.md) or [FlowItem](ts-container-flowitem.md). It can also be used within the **WaterFlow** or **FlowItem** component after being wrapped by custom components or [NodeContainer](ts-basic-components-nodecontainer.md). Lazy loading is supported only when the **WaterFlow** component uses single-column mode or single-column segments in segmented layout and the layout direction is **FlexDirection.Column**. Lazy loading is not supported if the **WaterFlow** component is in multi-column mode or the layout direction is **FlexDirection.Row** or **FlexDirection.RowReverse**. Using this component with **FlexDirection.ColumnReverse** in the **WaterFlow** component causes display anomalies. When lazy loading is enabled, the component only loads child components within the **WaterFlow** visible area, with pre-loading of half-screen content above and below the viewport during frame idle periods. > **NOTE** > > - This component is supported since API version 19. Updates will be marked with a superscript to indicate their earliest API version. > - This component's height adapts to content by default. Setting the height, height constraints, or aspect ratio causes display anomalies. ## APIs LazyVGridLayout() Creates a vertical lazy-loading grid layout container. **Atomic service API**: This API can be used in atomic services since API version 19. **System capability**: SystemCapability.ArkUI.ArkUI.Full ## Attributes In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported. ### columnsTemplate columnsTemplate(value: string) Sets the number of columns, fixed column width, or minimum column width of the grid. If this attribute is not set, one column will be used. For 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. **columnsTemplate('repeat(auto-fit, track-size)')**: The layout automatically calculates the number of columns and the actual column width, while adhering to the minimum column width specified with **track-size**. **columnsTemplate('repeat(auto-fill, track-size)')**: The layout automatically calculates the number of columns based on the fixed column width specified with **track-size**. **columnsTemplate('repeat(auto-stretch, track-size)')**: The layout uses **columnsGap** to define the minimum gap between columns and automatically calculates the number of columns and the actual gap size based on the fixed column width specified with **track-size**. **repeat**, **auto-fit**, **auto-fill**, and **auto-stretch** are keywords. **track-size** indicates the column width, in the unit of px, vp (default), %, or any valid digit. The value must be greater than or equal to one valid column width.
In **auto-stretch** mode, **track-size** must be a valid column width value, in the unit of px, vp, or any valid digit; percentage values (%) are not supported. If this attribute is set to **'0fr'**, the column width is 0, and child components are not displayed. If this attribute is set to an invalid value, the child components are displayed in a fixed column. **Atomic service API**: This API can be used in atomic services since API version 19. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Parameters** | Name| Type | Mandatory| Description | | ------ | ------ | ---- | ---------------------------------- | | value | string | Yes | Number of columns or minimum column width of the grid.| ### columnsGap columnsGap(value: LengthMetrics): T Sets the gap between columns. A value less than 0 evaluates to the default value. **Atomic service API**: This API can be used in atomic services since API version 19. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Parameters** | Name| Type | Mandatory| Description | | ------ | ---------------------------- | ---- | ---------------------------- | | value | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | Yes | Gap between columns.
Default value: **0vp**| **Return value** | Type| Description | | --- | -------------- | | T | Current component.| ### rowsGap rowsGap(value: LengthMetrics): T Sets the gap between rows. A value less than 0 evaluates to the default value. **Atomic service API**: This API can be used in atomic services since API version 19. **System capability**: SystemCapability.ArkUI.ArkUI.Full **Parameters** | Name| Type | Mandatory| Description | | ------ | ---------------------------- | ---- | ---------------------------- | | value | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | Yes | Gap between rows.
Default value: **0vp**| **Return value** | Type| Description | | --- | -------------- | | T | Current component.| ## Events Only the [universal events](ts-component-general-events.md) are supported. ## Example This example demonstrates how to implement a lazy-loading grid layout using the **WaterFlow** and **LazyVGridLayout** components. ```ts import { LengthMetrics } from '@kit.ArkUI' import { MyDataSource } from './MyDataSource' @Entry @Component struct LazyVGridLayoutSample1 { private arr:MyDataSource = new MyDataSource(); build() { Column() { WaterFlow() { LazyVGridLayout() { LazyForEach(this.arr, (item:number)=>{ Text("item" + item.toString()) .height(64) .width("100%") .borderRadius(5) .backgroundColor(Color.White) .textAlign(TextAlign.Center) }) } .columnsTemplate("1fr 1fr") .rowsGap(LengthMetrics.vp(10)) .columnsGap(LengthMetrics.vp(10)) }.padding(10) } .width('100%').height('100%') .backgroundColor("#DCDCDC") } aboutToAppear(): void { for (let i = 0; i < 100; i++) { this.arr.pushData(i); } } } ``` ```ts // MyDataSource.ets export class BasicDataSource implements IDataSource { private listeners: DataChangeListener[] = []; protected dataArray: T[] = []; public totalCount(): number { return this.dataArray.length; } public getData(index: number): T { return this.dataArray[index]; } registerDataChangeListener(listener: DataChangeListener): void { if (this.listeners.indexOf(listener) < 0) { console.info('add listener'); this.listeners.push(listener); } } unregisterDataChangeListener(listener: DataChangeListener): void { const pos = this.listeners.indexOf(listener); if (pos >= 0) { console.info('remove listener'); this.listeners.splice(pos, 1); } } notifyDataReload(): void { this.listeners.forEach(listener => { listener.onDataReloaded(); }) } notifyDataAdd(index: number): void { this.listeners.forEach(listener => { listener.onDataAdd(index); }) } notifyDataChange(index: number): void { this.listeners.forEach(listener => { listener.onDataChange(index); }) } notifyDataDelete(index: number): void { this.listeners.forEach(listener => { listener.onDataDelete(index); }) } notifyDataMove(from: number, to: number): void { this.listeners.forEach(listener => { listener.onDataMove(from, to); }) } notifyDatasetChange(operations: DataOperation[]): void { this.listeners.forEach(listener => { listener.onDatasetChange(operations); }) } } export class MyDataSource extends BasicDataSource { public shiftData(): void { this.dataArray.shift(); this.notifyDataDelete(0); } public unshiftData(data: T): void { this.dataArray.unshift(data); this.notifyDataAdd(0); } public pushData(data: T): void { this.dataArray.push(data); this.notifyDataAdd(this.dataArray.length - 1); } public popData(): void { this.dataArray.pop(); this.notifyDataDelete(this.dataArray.length); } public clearData(): void { this.dataArray = []; this.notifyDataReload(); } } ``` ![](figures/en-us_image_lazyvgridlayout1.png)