1# LazyVGridLayout 2 3The **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). 4 5Lazy 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. 6 7> **NOTE** 8> 9> - This component is supported since API version 19. Updates will be marked with a superscript to indicate their earliest API version. 10> - This component's height adapts to content by default. Setting the height, height constraints, or aspect ratio causes display anomalies. 11 12## APIs 13 14LazyVGridLayout() 15 16Creates a vertical lazy-loading grid layout container. 17 18**Atomic service API**: This API can be used in atomic services since API version 19. 19 20**System capability**: SystemCapability.ArkUI.ArkUI.Full 21 22## Attributes 23 24In addition to the [universal attributes](ts-component-general-attributes.md), the following attributes are supported. 25 26### columnsTemplate 27 28columnsTemplate(value: string) 29 30Sets 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. 31 32For 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. 33 34**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**. 35 36**columnsTemplate('repeat(auto-fill, track-size)')**: The layout automatically calculates the number of columns based on the fixed column width specified with **track-size**. 37 38**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**. 39 40**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.<br> 41In **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. 42 43If 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. 44 45**Atomic service API**: This API can be used in atomic services since API version 19. 46 47**System capability**: SystemCapability.ArkUI.ArkUI.Full 48 49**Parameters** 50 51| Name| Type | Mandatory| Description | 52| ------ | ------ | ---- | ---------------------------------- | 53| value | string | Yes | Number of columns or minimum column width of the grid.| 54 55### columnsGap 56 57columnsGap(value: LengthMetrics): T 58 59Sets the gap between columns. A value less than 0 evaluates to the default value. 60 61**Atomic service API**: This API can be used in atomic services since API version 19. 62 63**System capability**: SystemCapability.ArkUI.ArkUI.Full 64 65**Parameters** 66 67| Name| Type | Mandatory| Description | 68| ------ | ---------------------------- | ---- | ---------------------------- | 69| value | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | Yes | Gap between columns.<br>Default value: **0vp**| 70 71**Return value** 72 73| Type| Description | 74| --- | -------------- | 75| T | Current component.| 76 77### rowsGap 78 79rowsGap(value: LengthMetrics): T 80 81Sets the gap between rows. A value less than 0 evaluates to the default value. 82 83**Atomic service API**: This API can be used in atomic services since API version 19. 84 85**System capability**: SystemCapability.ArkUI.ArkUI.Full 86 87**Parameters** 88 89| Name| Type | Mandatory| Description | 90| ------ | ---------------------------- | ---- | ---------------------------- | 91| value | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | Yes | Gap between rows.<br>Default value: **0vp**| 92 93**Return value** 94 95| Type| Description | 96| --- | -------------- | 97| T | Current component.| 98 99## Events 100 101Only the [universal events](ts-component-general-events.md) are supported. 102 103## Example 104 105This example demonstrates how to implement a lazy-loading grid layout using the **WaterFlow** and **LazyVGridLayout** components. 106 107<!--code_no_check--> 108```ts 109import { LengthMetrics } from '@kit.ArkUI' 110import { MyDataSource } from './MyDataSource' 111 112@Entry 113@Component 114struct LazyVGridLayoutSample1 { 115 private arr:MyDataSource<number> = new MyDataSource<number>(); 116 build() { 117 Column() { 118 WaterFlow() { 119 LazyVGridLayout() { 120 LazyForEach(this.arr, (item:number)=>{ 121 Text("item" + item.toString()) 122 .height(64) 123 .width("100%") 124 .borderRadius(5) 125 .backgroundColor(Color.White) 126 .textAlign(TextAlign.Center) 127 }) 128 } 129 .columnsTemplate("1fr 1fr") 130 .rowsGap(LengthMetrics.vp(10)) 131 .columnsGap(LengthMetrics.vp(10)) 132 }.padding(10) 133 } 134 .width('100%').height('100%') 135 .backgroundColor("#DCDCDC") 136 } 137 138 aboutToAppear(): void { 139 for (let i = 0; i < 100; i++) { 140 this.arr.pushData(i); 141 } 142 } 143} 144``` 145 146<!--code_no_check--> 147```ts 148// MyDataSource.ets 149export class BasicDataSource<T> implements IDataSource { 150 private listeners: DataChangeListener[] = []; 151 protected dataArray: T[] = []; 152 153 public totalCount(): number { 154 return this.dataArray.length; 155 } 156 157 public getData(index: number): T { 158 return this.dataArray[index]; 159 } 160 161 registerDataChangeListener(listener: DataChangeListener): void { 162 if (this.listeners.indexOf(listener) < 0) { 163 console.info('add listener'); 164 this.listeners.push(listener); 165 } 166 } 167 168 unregisterDataChangeListener(listener: DataChangeListener): void { 169 const pos = this.listeners.indexOf(listener); 170 if (pos >= 0) { 171 console.info('remove listener'); 172 this.listeners.splice(pos, 1); 173 } 174 } 175 176 notifyDataReload(): void { 177 this.listeners.forEach(listener => { 178 listener.onDataReloaded(); 179 }) 180 } 181 182 notifyDataAdd(index: number): void { 183 this.listeners.forEach(listener => { 184 listener.onDataAdd(index); 185 }) 186 } 187 188 notifyDataChange(index: number): void { 189 this.listeners.forEach(listener => { 190 listener.onDataChange(index); 191 }) 192 } 193 194 notifyDataDelete(index: number): void { 195 this.listeners.forEach(listener => { 196 listener.onDataDelete(index); 197 }) 198 } 199 200 notifyDataMove(from: number, to: number): void { 201 this.listeners.forEach(listener => { 202 listener.onDataMove(from, to); 203 }) 204 } 205 206 notifyDatasetChange(operations: DataOperation[]): void { 207 this.listeners.forEach(listener => { 208 listener.onDatasetChange(operations); 209 }) 210 } 211} 212 213export class MyDataSource<T> extends BasicDataSource<T> { 214 public shiftData(): void { 215 this.dataArray.shift(); 216 this.notifyDataDelete(0); 217 } 218 public unshiftData(data: T): void { 219 this.dataArray.unshift(data); 220 this.notifyDataAdd(0); 221 } 222 public pushData(data: T): void { 223 this.dataArray.push(data); 224 this.notifyDataAdd(this.dataArray.length - 1); 225 } 226 public popData(): void { 227 this.dataArray.pop(); 228 this.notifyDataDelete(this.dataArray.length); 229 } 230 public clearData(): void { 231 this.dataArray = []; 232 this.notifyDataReload(); 233 } 234} 235``` 236 237 238