1# Grid
2
3The **Grid** component consists of cells formed by rows and columns. You can specify the cells where items are located to form various layouts.
4
5>  **NOTE**
6>
7>  This component is supported since API version 7. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## Child Components
11
12Only the [GridItem](ts-container-griditem.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.
13
14>  **NOTE**
15>
16>  Below are the rules for calculating the indexes of the child components of **Grid**:
17>
18>  The index increases in ascending order of child components.
19>
20>  In the **if/else** statement, only the child components in the branch where the condition is met participate in the index calculation.
21>
22>  In the **ForEach**, **LazyForEach**, or **Repeat** statement, the indexes of all expanded child nodes are calculated.
23>
24>  After changes occur in [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), or [Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md), the indexes of the child nodes are updated.
25>
26>  The child component that has the **visibility** attribute set to **Hidden** or **None** is included in the index calculation.
27>
28>  The child component that has the **visibility** attribute set to **None** is not displayed, but still takes up the corresponding cell.
29>
30>  The child component that has the **position** attribute set is displayed in the corresponding cell, offset by the distance specified by **position** relative to the upper left corner of the grid. This child component does not scroll with the corresponding cell and is not displayed after the corresponding cell extends beyond the display range of the grid.
31>
32>  When there is a gap between child components, it is filled as much as possible based on the current display area. Therefore, the relative position of grid items may change as the grid scrolls.
33
34## APIs
35
36Grid(scroller?: Scroller, layoutOptions?: GridLayoutOptions)
37
38**Atomic service API**: This API can be used in atomic services since API version 11.
39
40**System capability**: SystemCapability.ArkUI.ArkUI.Full
41
42**Parameters**
43
44| Name  | Type                                   | Mandatory| Description                                                    |
45| -------- | ------------------------------------------- | ---- | ------------------------------------------------------------ |
46| scroller | [Scroller](ts-container-scroll.md#scroller) | No  | Controller, which can be bound to scrollable components.<br>**NOTE**<br>The 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).|
47| layoutOptions<sup>10+</sup> | [GridLayoutOptions](#gridlayoutoptions10) | No| Grid layout options.|
48
49## GridLayoutOptions<sup>10+</sup>
50
51**Atomic service API**: This API can be used in atomic services since API version 11.
52
53**System capability**: SystemCapability.ArkUI.ArkUI.Full
54
55Defines the layout options. In this API, **irregularIndexes** and **onGetIrregularSizeByIndex** can be used for grids where either **rowsTemplate** or **columnsTemplate** is set. You can specify an index array and set the number of rows and columns to be occupied by a grid item with the specified index. For details, see Example 3. **onGetRectByIndex** can be used for grids where both **rowsTemplate** and **columnsTemplate** are set. It specifies the position and size for the grid item with the specified index. For details, see Example 1.
56
57**Parameters**
58
59| Name   | Type     | Mandatory  | Description                   |
60| ----- | ------- | ---- | --------------------- |
61| regularSize  | [number, number]  | Yes   | Number of rows and columns occupied by a grid item with regular size. The only supported value is **[1, 1]**, meaning that the grid item occupies one row and one column.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
62| irregularIndexes | number[] | No   | Indexes of the grid item with an irregular size in the grid. When **onGetIrregularSizeByIndex** is not set, the grid item specified in this parameter occupies an entire row of the grid that scrolls vertically or an entire column of the grid that scrolls horizontally.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
63| onGetIrregularSizeByIndex | (index: number) => [number, number] | No   | Number of rows and columns occupied by the grid item with an irregular size. This parameter is used together with **irregularIndexes**. In versions earlier than API version 12, the vertical scrolling grid does not support grid items spanning multiple rows, and the horizontal scrolling grid does not support grid items spanning multiple columns.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
64| onGetRectByIndex<sup>11+</sup> | (index: number) => [number, number,number,number] | No | Position and size of the grid item with the specified index, in the format of [rowStart,columnStart,rowSpan,columnSpan],<br>where **rowStart** indicates the row start position, **columnStart** indicates the column start position,<br>**rowSpan** indicates the number of rows occupied by the grid item, and **columnSpan** indicates the number of columns occupied by the grid item. Their values are unitless.<br>The values of **rowStart** and **columnStart** are natural numbers greater than or equal to 0. If a negative value is set, the default value **0** is used.<br>The values of **rowSpan** and **columnSpan** are natural numbers greater than or equal to 1. If a decimal is set, it is rounded down. If the decimal set is less than 1, the value **1** is used.<br>**NOTE**<br>Case 1: If a grid item finds that the start position specified for it is already occupied, it searches for an available start position from left to right and from top to bottom, starting from position [0,0].<br>Case 2: If any space other than the start position specified for a grid item is occupied, the grid item is displayed within the available space left.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
65
66## Attributes
67
68In 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.
69
70### columnsTemplate
71
72columnsTemplate(value: string)
73
74Sets 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.
75
76For 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.
77
78**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**.
79
80**columnsTemplate('repeat(auto-fill, track-size)')**: The layout automatically calculates the number of columns based on the fixed column width specified with **track-size**.
81
82**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**.
83
84**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>
85In **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.
86
87For visual reference, see [Example 8](#example-8).
88
89If this attribute is set to **'0fr'**, the column width is 0, and grid item in the column is not displayed. If this attribute is set to any other invalid value, the grid item is displayed as one column.
90
91**Atomic service API**: This API can be used in atomic services since API version 11.
92
93**System capability**: SystemCapability.ArkUI.ArkUI.Full
94
95**Parameters**
96
97| Name| Type  | Mandatory| Description                              |
98| ------ | ------ | ---- | ---------------------------------- |
99| value  | string | Yes  | Number of columns or minimum column width of the grid.|
100
101### rowsTemplate
102
103rowsTemplate(value: string)
104
105Sets the number of rows, fixed row height, or minimum row height of the grid. If this attribute is not set, one row will be used.
106
107For 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.
108
109**rowsTemplate('repeat(auto-fit, track-size)')**: The layout automatically calculates the number of rows and the actual row height, while adhering to the minimum row height specified with **track-size**.
110
111**rowsTemplate('repeat(auto-fill, track-size)')**: The layout automatically calculates the number of rows based on the fixed row height specified with **track-size**.
112
113**rowsTemplate('repeat(auto-stretch, track-size)')**: The layout uses **rowsGap** to define the minimum gap between rows and automatically calculates the number of rows and the actual gap size based on the fixed row height specified with **track-size**.
114
115**repeat**, **auto-fit**, **auto-fill**, and **auto-stretch** are keywords. **track-size** indicates the row height, in the unit of px, vp (default), %, or any valid digit. The value must be greater than or equal to one valid row height.<br>
116In **auto-stretch** mode, **track-size** must be a valid row height value, in the unit of px, vp, or any valid digit; percentage values (%) are not supported.
117
118If this attribute is set to **'0fr'**, the row width is 0, and grid item in the row is not displayed. If this attribute is set to any other invalid value, the grid item is displayed as one row.
119
120**Atomic service API**: This API can be used in atomic services since API version 11.
121
122**System capability**: SystemCapability.ArkUI.ArkUI.Full
123
124**Parameters**
125
126| Name| Type  | Mandatory| Description                              |
127| ------ | ------ | ---- | ---------------------------------- |
128| value  | string | Yes  | Number of rows or minimum row height of the grid.|
129
130>  **NOTE**
131>
132>  Depending on the settings of the **rowsTemplate** and **columnsTemplate** attributes, the **Grid** component supports the following layout modes:
133>
134>  1. **rowsTemplate** and **columnsTemplate** are both set
135>
136>  - The **Grid** component displays only elements in a fixed number of rows and columns and cannot be scrolled.
137>  - In this mode, the following attributes do not take effect: **layoutDirection**, **maxCount**, **minCount**, and **cellLength**.
138>  - If the width and height of a grid are not set, the grid adapts to the size of its parent component by default.
139>  - The size of the grid rows and columns is the size of the grid content area minus the gap between rows and columns. It is allocated based on the proportion of each row and column.
140>  - By default, the grid items fill the entire grid.
141>
142>  2. Either **rowsTemplate** or **columnsTemplate** is set
143>
144>  - The **Grid** component arranges elements in the specified direction and allows for scrolling to display excess elements.
145>  - If **columnsTemplate** is set, the component scrolls vertically, the main axis runs vertically, and the cross axis runs horizontally.
146>  - If **rowsTemplate** is set, the component scrolls horizontally, the main axis runs horizontally, and the cross axis runs vertically.
147>  - In this mode, the following attributes do not take effect: **layoutDirection**, **maxCount**, **minCount**, and **cellLength**.
148>  - The cross axis size of the grid is the cross axis size of the grid content area minus the gaps along the cross axis. It is allocated based on the proportion of each row and column.
149>  - The main axis size of the grid is the maximum height of all grid items in the cross axis direction of the current grid.
150>
151>  3. Neither **rowsTemplate** nor **columnsTemplate** is set
152>
153>  - The **Grid** component arranges elements in the direction specified by **layoutDirection**. The number of columns is jointly determined by the grid width, width of the first element, **minCount**, **maxCount**, and **columnsGap**.
154>  - The number of rows is jointly determined by the grid height, height of the first element, **cellLength**, and **rowsGap**. Elements outside the determined range of rows and columns are not displayed and cannot be viewed through scrolling.
155>  - In this mode, only the following attributes take effect: **layoutDirection**, **maxCount**, **minCount**, **cellLength**, **editMode**, **columnsGap**, and **rowsGap**.
156>  - When **layoutDirection** is set to **Row**, child components are arranged from left to right. When a row is full, a new row will be added. If the remaining height is insufficient, no more elements will be laid out, and the whole content is centered at the top.
157>  - When **layoutDirection** is set to **Column**, elements are arranged column by column from top to bottom. If the remaining height is insufficient, no more elements will be laid out, and the whole content is centered at the top.
158>  - If there are no grid items in the grid, the width and height of the grid are set to 0.
159>
160
161### columnsGap
162
163columnsGap(value: Length)
164
165Sets the gap between columns. A value less than 0 evaluates to the default value.
166
167**Atomic service API**: This API can be used in atomic services since API version 11.
168
169**System capability**: SystemCapability.ArkUI.ArkUI.Full
170
171**Parameters**
172
173| Name| Type                        | Mandatory| Description                        |
174| ------ | ---------------------------- | ---- | ---------------------------- |
175| value  | [Length](ts-types.md#length) | Yes  | Gap between columns.<br>Default value: **0**|
176
177### rowsGap
178
179rowsGap(value: Length)
180
181Sets the gap between rows. A value less than 0 evaluates to the default value.
182
183**Atomic service API**: This API can be used in atomic services since API version 11.
184
185**System capability**: SystemCapability.ArkUI.ArkUI.Full
186
187**Parameters**
188
189| Name| Type                        | Mandatory| Description                        |
190| ------ | ---------------------------- | ---- | ---------------------------- |
191| value  | [Length](ts-types.md#length) | Yes  | Gap between rows.<br>Default value: **0**|
192
193### scrollBar
194
195scrollBar(value: BarState)
196
197Sets the scrollbar state.
198
199**Atomic service API**: This API can be used in atomic services since API version 11.
200
201**System capability**: SystemCapability.ArkUI.ArkUI.Full
202
203**Parameters**
204
205| Name| Type                                     | Mandatory| Description                                                        |
206| ------ | ----------------------------------------- | ---- | ------------------------------------------------------------ |
207| value  | [BarState](ts-appendix-enums.md#barstate) | Yes  | Scrollbar state.<br>Default value: **BarState.Auto**<br>**NOTE**<br>In API version 9 and earlier versions, the default value is **BarState.Off**. Since API version 10, the default value is **BarState.Auto**.|
208
209### scrollBarColor
210
211scrollBarColor(value: Color | number | string)
212
213Sets the scrollbar color.
214
215**Atomic service API**: This API can be used in atomic services since API version 11.
216
217**System capability**: SystemCapability.ArkUI.ArkUI.Full
218
219**Parameters**
220
221| Name| Type                                                        | Mandatory| Description          |
222| ------ | ------------------------------------------------------------ | ---- | -------------- |
223| value  | [Color](ts-appendix-enums.md#color) \| number \| string | Yes  | Scrollbar color.<br>Default value: **'\#182431'** (40% opacity)|
224
225### scrollBarWidth
226
227scrollBarWidth(value: number | string)
228
229Sets the scrollbar width. This attribute cannot be set in percentage. After the width is set, the scrollbar is displayed with the set width in normal state and pressed state. If the set width exceeds the height of the **Grid** component on the main axis, the scrollbar reverts to the default width.
230
231**Atomic service API**: This API can be used in atomic services since API version 11.
232
233**System capability**: SystemCapability.ArkUI.ArkUI.Full
234
235**Parameters**
236
237| Name| Type                      | Mandatory| Description                                     |
238| ------ | -------------------------- | ---- | ----------------------------------------- |
239| value  | number \| string | Yes  | Scrollbar width.<br>Default value: **4**<br>Unit: vp|
240
241### cachedCount
242
243cachedCount(value: number)
244
245Sets the number of grid items to be preloaded (cached). It works only in [LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md) and [Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md) with the **virtualScroll** option enabled. A value less than 0 evaluates to the default value. <!--Del-->For details, see [Minimizing White Blocks During Swiping](../../../performance/arkts-performance-improvement-recommendation.md#minimizing-white-blocks-during-swiping).<!--DelEnd-->
246
247The number of the grid items to be cached before and after the currently displayed one equals the value of **cachedCount** multiplied by the number of columns.
248
249In [LazyForEach](../../../quick-start/arkts-rendering-control-lazyforeach.md) and [Repeat](../../../quick-start/arkts-new-rendering-control-repeat.md) with the **virtualScroll** option enabled, grid items that are outside the display and cache range will be released.
250
251**Atomic service API**: This API can be used in atomic services since API version 11.
252
253**System capability**: SystemCapability.ArkUI.ArkUI.Full
254
255**Parameters**
256
257| Name| Type  | Mandatory| Description                                  |
258| ------ | ------ | ---- | -------------------------------------- |
259| value  | number | Yes  | Number of grid items to be preloaded (cached).<br>Default value: **1**|
260
261### editMode<sup>8+</sup>
262
263editMode(value: boolean)
264
265Sets whether to enable edit mode. In edit mode, the user can drag the [grid items](ts-container-griditem.md) in the **Grid** component.
266
267**Atomic service API**: This API can be used in atomic services since API version 11.
268
269**System capability**: SystemCapability.ArkUI.ArkUI.Full
270
271**Parameters**
272
273| Name| Type  | Mandatory| Description                                    |
274| ------ | ------ | ---- | ---------------------------------------- |
275| value  | boolean | Yes  | Whether to enable edit mode.<br>Default value: **false**|
276
277### layoutDirection<sup>8+</sup>
278
279layoutDirection(value: GridDirection)
280
281Sets the main axis direction of the grid.
282
283**Atomic service API**: This API can be used in atomic services since API version 11.
284
285**System capability**: SystemCapability.ArkUI.ArkUI.Full
286
287**Parameters**
288
289| Name| Type                                    | Mandatory| Description                                          |
290| ------ | ---------------------------------------- | ---- | ---------------------------------------------- |
291| value  | [GridDirection](#griddirection8) | Yes  | Main axis direction of the grid.<br>Default value: **GridDirection.Row**|
292
293### maxCount<sup>8+</sup>
294
295maxCount(value: number)
296
297Sets the maximum number of rows or columns that can be displayed. A value less than 1 evaluates to the default value.
298
299When **layoutDirection** is **Row** or **RowReverse**, the value indicates the maximum number of columns that can be displayed.
300
301When **layoutDirection** is **Column** or **ColumnReverse**, the value indicates the maximum number of rows that can be displayed.
302
303If the value of **maxCount** is smaller than that of **minCount**, the default values of **maxCount** and **minCount** are used.
304
305**Atomic service API**: This API can be used in atomic services since API version 11.
306
307**System capability**: SystemCapability.ArkUI.ArkUI.Full
308
309**Parameters**
310
311| Name| Type  | Mandatory| Description                                         |
312| ------ | ------ | ---- | --------------------------------------------- |
313| value  | number | Yes  | Maximum number of rows or columns that can be displayed.<br>Default value: **Infinity**|
314
315### minCount<sup>8+</sup>
316
317minCount(value: number)
318
319Sets the minimum number of rows or columns that can be displayed. A value less than 1 evaluates to the default value.
320
321When **layoutDirection** is **Row** or **RowReverse**, the value indicates the minimum number of columns that can be displayed.
322
323When **layoutDirection** is **Column** or **ColumnReverse**, the value indicates the minimum number of rows that can be displayed.
324
325**Atomic service API**: This API can be used in atomic services since API version 11.
326
327**System capability**: SystemCapability.ArkUI.ArkUI.Full
328
329**Parameters**
330
331| Name| Type  | Mandatory| Description                                  |
332| ------ | ------ | ---- | -------------------------------------- |
333| value  | number | Yes  | Minimum number of rows or columns that can be displayed.<br>Default value: **1**|
334
335### cellLength<sup>8+</sup>
336
337cellLength(value: number)
338
339Sets the height per row or width per column.
340
341When **layoutDirection** is **Row** or **RowReverse**, the value indicates the height per row.
342
343When **layoutDirection** is **Column** or **ColumnReverse**, the value indicates the width per column.
344
345**Atomic service API**: This API can be used in atomic services since API version 11.
346
347**System capability**: SystemCapability.ArkUI.ArkUI.Full
348
349**Parameters**
350
351| Name| Type  | Mandatory| Description                                                   |
352| ------ | ------ | ---- | ------------------------------------------------------- |
353| value  | number | Yes  | Height per row or width per column.<br>Default value: size of the first element<br>Unit: vp|
354
355### multiSelectable<sup>8+</sup>
356
357multiSelectable(value: boolean)
358
359Sets whether to enable multiselect. When multiselect is enabled, you can use the **selected** attribute and **onSelect** event to obtain the selected status of grid items; you can also set the [style](./ts-universal-attributes-polymorphic-style.md) for the selected state (by default, no style is set for the selected state).
360
361**Atomic service API**: This API can be used in atomic services since API version 11.
362
363**System capability**: SystemCapability.ArkUI.ArkUI.Full
364
365**Parameters**
366
367| Name| Type   | Mandatory| Description                                                        |
368| ------ | ------- | ---- | ------------------------------------------------------------ |
369| value  | boolean | Yes  | Whether to enable multiselect.<br>Default value: **false**<br>**false**: Multiselect is disabled. **true**: Multiselect is disabled.|
370
371### supportAnimation<sup>8+</sup>
372
373supportAnimation(value: boolean)
374
375Sets whether to enable animation. Currently, the grid item drag animation is supported. Animation is supported only in scrolling mode (only **rowsTemplate** or **columnsTemplate** is set).<br>Drag animations are only supported in grids with fixed size rules; scenarios involving spanning across rows or columns are not supported.
376
377**Atomic service API**: This API can be used in atomic services since API version 11.
378
379**System capability**: SystemCapability.ArkUI.ArkUI.Full
380
381**Parameters**
382
383| Name| Type   | Mandatory| Description                            |
384| ------ | ------- | ---- | -------------------------------- |
385| value  | boolean | Yes  | Whether to enable animation.<br>Default value: **false**|
386
387### edgeEffect<sup>10+</sup>
388
389edgeEffect(value: EdgeEffect, options?: EdgeEffectOptions)
390
391Sets the effect used when the scroll boundary is reached.
392
393**Atomic service API**: This API can be used in atomic services since API version 11.
394
395**System capability**: SystemCapability.ArkUI.ArkUI.Full
396
397**Parameters**
398
399| Name               | Type                                                        | Mandatory| Description                                                        |
400| --------------------- | ------------------------------------------------------------ | ---- | ------------------------------------------------------------ |
401| value                 | [EdgeEffect](ts-appendix-enums.md#edgeeffect)                | Yes  | Effect used when the scroll boundary is reached. The spring and shadow effects are supported.<br>Default value: **EdgeEffect.None**|
402| options<sup>11+</sup> | [EdgeEffectOptions](ts-container-scrollable-common.md#edgeeffectoptions11) | No  | Whether to enable the scroll effect when the component content is smaller than the component itself. The value **{ alwaysEnabled: true }** means to enable the scroll effect, and **{ alwaysEnabled: false }** means the opposite.<br>Default value: **{ alwaysEnabled: false }**|
403
404### enableScrollInteraction<sup>10+</sup>
405
406enableScrollInteraction(value: boolean)
407
408Sets 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.
409
410**Atomic service API**: This API can be used in atomic services since API version 11.
411
412**System capability**: SystemCapability.ArkUI.ArkUI.Full
413
414**Parameters**
415
416| Name| Type   | Mandatory| Description                               |
417| ------ | ------- | ---- | ----------------------------------- |
418| value  | boolean | Yes  | Whether to support scroll gestures.<br>Default value: **true**|
419
420### nestedScroll<sup>10+</sup>
421
422nestedScroll(value: NestedScrollOptions)
423
424Sets the nested scrolling options. You can set the nested scrolling mode in the forward and backward directions to implement scrolling linkage with the parent component.
425
426**Atomic service API**: This API can be used in atomic services since API version 11.
427
428**System capability**: SystemCapability.ArkUI.ArkUI.Full
429
430**Parameters**
431
432| Name| Type                                                        | Mandatory| Description          |
433| ------ | ------------------------------------------------------------ | ---- | -------------- |
434| value  | [NestedScrollOptions](ts-container-scrollable-common.md#nestedscrolloptions10) | Yes  | Nested scrolling options.|
435
436### friction<sup>10+</sup>
437
438friction(value: number | Resource)
439
440Sets 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. A value less than or equal to 0 evaluates to the default value.
441
442**Atomic service API**: This API can be used in atomic services since API version 11.
443
444**System capability**: SystemCapability.ArkUI.ArkUI.Full
445
446**Parameters**
447
448| Name| Type                                                | Mandatory| Description                                                       |
449| ------ | ---------------------------------------------------- | ---- | ----------------------------------------------------------- |
450| 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**.|
451
452### alignItems<sup>12+</sup>
453
454alignItems(alignment: Optional\<GridItemAlignment\>)
455
456Sets the alignment mode of grid items in the grid. For details, see [Example 9](#example-9).
457
458**Atomic service API**: This API can be used in atomic services since API version 12.
459
460**System capability**: SystemCapability.ArkUI.ArkUI.Full
461
462**Parameters**
463
464| Name    | Type  | Mandatory| Description                           |
465| ---------- | ------ | ---- | ------------------------------- |
466| alignment | Optional\<[GridItemAlignment](#griditemalignment12)\> | Yes  | Alignment mode of grid items in the grid.<br>Default value: **GridItemAlignment.DEFAULT**|
467
468## GridItemAlignment<sup>12+</sup>
469
470**Atomic service API**: This API can be used in atomic services since API version 12.
471
472**System capability**: SystemCapability.ArkUI.ArkUI.Full
473
474| Name  | Value| Description                                  |
475| ------ |------| -------------------------------------- |
476| DEFAULT  |  0  | Use the default alignment mode of the grid.|
477| STRETCH |  1  | Use the height of the tallest grid item in a row as the height for all other grid items in that row.|
478
479
480> **NOTE**
481>
482> 1. The **STRETCH** option only takes effect in scrollable grids.<br>
483> 2. The **STRETCH** option takes effect only if each grid item in a row is of a regular size (occupying only one row and one column). It is not effective in scenarios where there are grid items spanning across rows or columns.<br>
484> 3. When **STRETCH** is used, only grid items without a set height will adopt the height of the tallest grid item in the current row; the height of grid items with a set height will remain unchanged.<br>
485> 4. When **STRETCH** is used, the grid undergoes an additional layout process, which may incur additional performance overhead.
486
487## GridDirection<sup>8+</sup>
488
489**Atomic service API**: This API can be used in atomic services since API version 11.
490
491**System capability**: SystemCapability.ArkUI.ArkUI.Full
492
493| Name  |Value| Description                                  |
494| ------ |------| -------------------------------------- |
495| Row  |  0  | Horizontal layout, where the child components are arranged from left to right as the main axis runs along the rows.|
496| Column |  1  | Vertical layout, where the child components are arranged from top to bottom as the main axis runs down the columns.|
497| RowReverse    |  2  | Reverse horizontal layout, where the child components are arranged from right to left as the main axis runs along the rows.|
498| ColumnReverse   |  3  | Reverse vertical layout, where the child components are arranged from bottom up as the main axis runs down the columns.|
499
500> **NOTE**
501>
502> The default value of the universal attribute [clip](ts-universal-attributes-sharp-clipping.md) is **true** for the **Grid** component.
503
504## Events
505
506In 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.
507
508### onScrollIndex
509
510onScrollIndex(event: (first: number, last: number) => void)
511
512Triggered when the first or last item displayed in the grid changes, that is, when the index of either the first or last item changes. It is triggered once when the grid is initialized.  
513
514**Atomic service API**: This API can be used in atomic services since API version 11.
515
516**System capability**: SystemCapability.ArkUI.ArkUI.Full
517
518**Parameters**
519
520| Name            | Type  | Mandatory| Description                            |
521| ------------------ | ------ | ---- | -------------------------------- |
522| first              | number | Yes  | Index of the first item of the grid.|
523| last<sup>10+</sup> | number | Yes  | Index of the last item of the grid.|
524
525### onItemDragStart<sup>8+</sup>
526
527onItemDragStart(event: (event: ItemDragInfo, itemIndex: number) => (() => any) \| void)
528
529Triggered when a grid item starts to be dragged. If **void** is returned, the drag operation cannot be performed.
530
531This event is triggered when the user long presses a grid item.
532
533Drag gesture recognition is also initiated by a long press, and the event processing mechanism prioritizes child component events. Therefore, when the grid item is bound to the long press gesture, it cannot be dragged. In light of this, if both long press and drag operations are required on the grid item, you can use the universal drag event.
534
535**Atomic service API**: This API can be used in atomic services since API version 11.
536
537**System capability**: SystemCapability.ArkUI.ArkUI.Full
538
539**Parameters**
540
541| Name   | Type                                 | Mandatory| Description                  |
542| --------- | ------------------------------------- | ---- | ---------------------- |
543| event     | [ItemDragInfo](ts-container-scrollable-common.md#itemdraginfo) | Yes  | Information about the drag point.        |
544| itemIndex | number                                | Yes  | Index of the dragged item.|
545
546### onItemDragEnter<sup>8+</sup>
547
548onItemDragEnter(event: (event: ItemDragInfo) => void)
549
550Triggered when the dragged item enters the drop target of the grid.
551
552**Atomic service API**: This API can be used in atomic services since API version 11.
553
554**System capability**: SystemCapability.ArkUI.ArkUI.Full
555
556**Parameters**
557
558| Name| Type                                 | Mandatory| Description          |
559| ------ | ------------------------------------- | ---- | -------------- |
560| event  | [ItemDragInfo](ts-container-scrollable-common.md#itemdraginfo) | Yes  | Information about the drag point.|
561
562### onItemDragMove<sup>8+</sup>
563
564onItemDragMove(event: (event: ItemDragInfo, itemIndex: number, insertIndex: number) => void)
565
566Triggered when the dragged item moves over the drop target of the grid.
567
568**Atomic service API**: This API can be used in atomic services since API version 11.
569
570**System capability**: SystemCapability.ArkUI.ArkUI.Full
571
572**Parameters**
573
574| Name     | Type                                 | Mandatory| Description          |
575| ----------- | ------------------------------------- | ---- | -------------- |
576| event       | [ItemDragInfo](ts-container-scrollable-common.md#itemdraginfo) | Yes  | Information about the drag point.|
577| itemIndex   | number                                | Yes  | Initial position of the dragged item.|
578| insertIndex | number                                | Yes  | Index of the position to which the dragged item is dropped.|
579
580### onItemDragLeave<sup>8+</sup>
581
582onItemDragLeave(event: (event: ItemDragInfo, itemIndex: number) => void)
583
584Triggered when the dragged item leaves the drop target of the grid.
585
586**Atomic service API**: This API can be used in atomic services since API version 11.
587
588**System capability**: SystemCapability.ArkUI.ArkUI.Full
589
590**Parameters**
591
592| Name   | Type                                 | Mandatory| Description                      |
593| --------- | ------------------------------------- | ---- | -------------------------- |
594| event     | [ItemDragInfo](ts-container-scrollable-common.md#itemdraginfo) | Yes  | Information about the drag point.            |
595| itemIndex | number                                | Yes  | Index of the dragged item.|
596
597### onItemDrop<sup>8+</sup>
598
599onItemDrop(event: (event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => void)
600
601Triggered when the dragged item is dropped on the drop target of the grid.
602
603**Atomic service API**: This API can be used in atomic services since API version 11.
604
605**System capability**: SystemCapability.ArkUI.ArkUI.Full
606
607**Parameters**
608
609| Name     | Type                                 | Mandatory| Description          |
610| ----------- | ------------------------------------- | ---- | -------------- |
611| event       | [ItemDragInfo](ts-container-scrollable-common.md#itemdraginfo) | Yes  | Information about the drag point.|
612| itemIndex   | number                                | Yes  | Initial position of the dragged item.|
613| insertIndex | number                                | Yes  | Index of the position to which the dragged item is dropped.|
614| isSuccess   | boolean                               | Yes  | Whether the dragged item is successfully dropped.  |
615
616### onScrollBarUpdate<sup>10+</sup>
617
618onScrollBarUpdate(event: (index: number, offset: number) => ComputedBarAttribute)
619
620Triggered when the first item displayed in the grid changes. You can use the callback to set the position and length of the scrollbar.
621
622This API is intended solely for setting the scroll position of the grid. Avoid implementing service logic within this API.
623
624**Atomic service API**: This API can be used in atomic services since API version 11.
625
626**System capability**: SystemCapability.ArkUI.ArkUI.Full
627
628**Parameters**
629
630| Name| Type  | Mandatory| Description                                                        |
631| ------ | ------ | ---- | ------------------------------------------------------------ |
632| index  | number | Yes  | Index of the first item of the grid.                            |
633| offset | number | Yes  | Offset of the displayed first item relative to the start position of the grid, in vp.|
634
635**Return value**
636
637| Type                                                 | Description                |
638| ----------------------------------------------------- | -------------------- |
639| [ComputedBarAttribute](#computedbarattribute10) | Position and length of the scrollbar.|
640
641### onReachStart<sup>10+</sup>
642
643onReachStart(event: () => void)
644
645Triggered when the grid reaches the start position.
646
647This event is triggered once when the grid is initialized and once when the grid scrolls to the start position. If the edge effect is set to a spring effect, this event is triggered once when the swipe passes the start position, and triggered again when the swipe rebounds back to the start position.
648
649**Atomic service API**: This API can be used in atomic services since API version 11.
650
651**System capability**: SystemCapability.ArkUI.ArkUI.Full
652
653### onReachEnd<sup>10+</sup>
654
655onReachEnd(event: () => void)
656
657Triggered when the grid reaches the end position.
658
659If the edge effect is set to a spring effect, this event is triggered once when the swipe passes the end position, and triggered again when the swipe rebounds back to the end position.
660
661**Atomic service API**: This API can be used in atomic services since API version 11.
662
663**System capability**: SystemCapability.ArkUI.ArkUI.Full
664
665### onScrollFrameBegin<sup>10+</sup>
666
667onScrollFrameBegin(event: (offset: number, state:  ScrollState) => { offsetRemain: number })
668
669Triggered when the grid starts to scroll. After the amount by which the grid will scroll is passed in, the event handler works out the amount by which the grid needs to scroll based on the real-world situation and returns the result.
670
671**Atomic service API**: This API can be used in atomic services since API version 11.
672
673**System capability**: SystemCapability.ArkUI.ArkUI.Full
674
675**Parameters**
676
677| Name| Type                                                   | Mandatory| Description                      |
678| ------ | ------------------------------------------------------- | ---- | -------------------------- |
679| offset | number                                                  | Yes  | Amount to scroll by, in vp.|
680| state  | [ScrollState](ts-container-list.md#scrollstate) | Yes  | Current scroll state.            |
681
682**Return value**
683
684| Type                    | Description                |
685| ------------------------ | -------------------- |
686| { offsetRemain: number } | Actual amount by which the grid scrolls, in vp.|
687
688### onScrollStart<sup>10+</sup>
689
690onScrollStart(event: () => void)
691
692Triggered when the grid starts scrolling initiated by the user's finger dragging the grid or its scrollbar. This event is also triggered when the animation contained in the scrolling triggered by [Scroller](ts-container-scroll.md#scroller) starts.
693
694**Atomic service API**: This API can be used in atomic services since API version 11.
695
696**System capability**: SystemCapability.ArkUI.ArkUI.Full
697
698### onScrollStop<sup>10+</sup>
699
700onScrollStop(event: () => void)
701
702Triggered when the grid stops scrolling after the user's finger leaves the screen. This event is also triggered when the animation contained in the scrolling triggered by [Scroller](ts-container-scroll.md#scroller) stops.
703
704**Atomic service API**: This API can be used in atomic services since API version 11.
705
706**System capability**: SystemCapability.ArkUI.ArkUI.Full
707
708### onScroll<sup>(deprecated)</sup>
709onScroll(event: (scrollOffset: number, scrollState: [ScrollState](ts-container-list.md#scrollstate)) => void) 
710
711Triggered when the grid scrolls.
712
713This API is supported since API version 10 and deprecated since API version 12. You are advised to use [onDidScroll](ts-container-scrollable-common.md#ondidscroll12) instead.
714
715**Atomic service API**: This API can be used in atomic services since API version 11.
716
717**System capability**: SystemCapability.ArkUI.ArkUI.Full
718
719**Parameters**
720
721| Name| Type| Mandatory| Description|
722| ------ | ------ | ------ | ------|
723| scrollOffset | number | Yes| Scroll offset of each frame. The offset is positive when the grid is scrolled up and negative when the grid is scrolled down.<br>Unit: vp|
724| scrollState | [ScrollState](ts-container-list.md#scrollstate) | Yes| Current scroll state.|
725
726## ComputedBarAttribute<sup>10+</sup>
727
728**Atomic service API**: This API can be used in atomic services since API version 11.
729
730**System capability**: SystemCapability.ArkUI.ArkUI.Full
731
732| Name        | Type        | Read Only| Optional|   Description        |
733| ----------- | ------------ | ---- | ---- | ---------- |
734| totalOffset | number | No| No|  Total offset of the grid content relative to the display area, in px.   |
735| totalLength   | number | No| No|  Total length of the grid content, in px.   |
736
737## Example
738
739### Example 1
740
741This example shows a grid with fixed number of rows and columns, for which you can use **onGetRectByIndex** in **GridLayoutOptions** to specify the position and size of grid items.
742
743```ts
744// xxx.ets
745@Entry
746@Component
747struct GridExample {
748  @State numbers1: String[] = ['0', '1', '2', '3', '4']
749  @State numbers2: String[] = ['0', '1','2','3','4','5']
750
751  layoutOptions3: GridLayoutOptions = {
752    regularSize: [1, 1],
753    onGetRectByIndex: (index: number) => {
754      if (index == 0)
755        return [0, 0, 1, 1]
756      else if(index==1)
757        return [0, 1, 2, 2]
758      else if(index==2)
759        return [0 ,3 ,3 ,3]
760      else if(index==3)
761        return [3, 0, 3, 3]
762      else if(index==4)
763        return [4, 3, 2, 2]
764      else
765        return [5, 5, 1, 1]
766    }
767  }
768
769  build() {
770    Column({ space: 5 }) {
771      Grid() {
772        ForEach(this.numbers1, (day: string) => {
773          ForEach(this.numbers1, (day: string) => {
774            GridItem() {
775              Text(day)
776                .fontSize(16)
777                .backgroundColor(0xF9CF93)
778                .width('100%')
779                .height('100%')
780                .textAlign(TextAlign.Center)
781            }
782          }, (day: string) => day)
783        }, (day: string) => day)
784      }
785      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
786      .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
787      .columnsGap(10)
788      .rowsGap(10)
789      .width('90%')
790      .backgroundColor(0xFAEEE0)
791      .height(300)
792
793      Text('Use of GridLayoutOptions: onGetRectByIndex').fontColor(0xCCCCCC).fontSize(9).width('90%')
794
795      Grid(undefined, this.layoutOptions3) {
796        ForEach(this.numbers2, (day: string) => {
797          GridItem() {
798            Text(day)
799              .fontSize(16)
800              .backgroundColor(0xF9CF93)
801              .width('100%')
802              .height("100%")
803              .textAlign(TextAlign.Center)
804          }
805          .height("100%")
806          .width('100%')
807        }, (day: string) => day)
808      }
809      .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
810      .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
811      .columnsGap(10)
812      .rowsGap(10)
813      .width('90%')
814      .backgroundColor(0xFAEEE0)
815      .height(300)
816    }.width('100%').margin({ top: 5 })
817  }
818}
819```
820
821![en-us_image_0000001219744183](figures/en-us_image_0000001219744183.gif)
822
823### Example 2
824
825This example shows a scrollable grid with all its scrolling attributes and events specified.
826
827```ts
828// xxx.ets
829@Entry
830@Component
831struct GridExample {
832  @State numbers: String[] = ['0', '1', '2', '3', '4']
833  scroller: Scroller = new Scroller()
834  @State gridPosition: number = 0 // 0 indicates scrolling to the top of the grid, 1 indicates scrolling to the center, and 2 indicates scrolling to the bottom.
835
836  build() {
837    Column({ space: 5 }) {
838      Text('scroll').fontColor(0xCCCCCC).fontSize(9).width('90%')
839      Grid(this.scroller) {
840        ForEach(this.numbers, (day: string) => {
841          ForEach(this.numbers, (day: string) => {
842            GridItem() {
843              Text(day)
844                .fontSize(16)
845                .backgroundColor(0xF9CF93)
846                .width('100%')
847                .height(80)
848                .textAlign(TextAlign.Center)
849            }
850          }, (day: string) => day)
851        }, (day: string) => day)
852      }
853      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
854      .columnsGap(10)
855      .rowsGap(10)
856      .friction(0.6)
857      .enableScrollInteraction(true)
858      .supportAnimation(false)
859      .multiSelectable(false)
860      .edgeEffect(EdgeEffect.Spring)
861      .scrollBar(BarState.On)
862      .scrollBarColor(Color.Grey)
863      .scrollBarWidth(4)
864      .width('90%')
865      .backgroundColor(0xFAEEE0)
866      .height(300)
867      .onScrollIndex((first: number, last: number) => {
868        console.info(first.toString())
869        console.info(last.toString())
870      })
871      .onScrollBarUpdate((index: number, offset: number) => {
872        console.info("XXX" + 'Grid onScrollBarUpdate,index : ' + index.toString() + ",offset" + offset.toString())
873        return { totalOffset: (index / 5) * (80 + 10) - offset, totalLength: 80 * 5 + 10 * 4 }
874      }) // The sample code applies only to the current data source. If the data source changes, modify the code or delete this attribute.
875      .onDidScroll((scrollOffset: number, scrollState: ScrollState) => {
876        console.info(scrollOffset.toString())
877        console.info(scrollState.toString())
878      })
879      .onScrollStart(() => {
880        console.info("XXX" + "Grid onScrollStart")
881      })
882      .onScrollStop(() => {
883        console.info("XXX" + "Grid onScrollStop")
884      })
885      .onReachStart(() => {
886        this.gridPosition = 0
887        console.info("XXX" + "Grid onReachStart")
888      })
889      .onReachEnd(() => {
890        this.gridPosition = 2
891        console.info("XXX" + "Grid onReachEnd")
892      })
893
894      Button('next page')
895        .onClick(() => {// Click to go to the next page.
896          this.scroller.scrollPage({ next: true })
897        })
898    }.width('100%').margin({ top: 5 })
899  }
900}
901```
902
903![scrollerExample2](figures/scrollerExample2.gif)
904
905### Example 3
906
907This example uses **irregularIndexes** and **onGetIrregularSizeByIndex** in **GridLayoutOptions**.
908
909```ts
910// xxx.ets
911@Entry
912@Component
913struct GridExample {
914  @State numbers: String[] = ['0', '1', '2', '3', '4']
915  scroller: Scroller = new Scroller()
916  layoutOptions1: GridLayoutOptions = {
917    regularSize: [1, 1],        // Only [1, 1] is supported.
918    irregularIndexes: [0, 6], // The grid item whose indexes are 0 and 6 occupies one row.
919  }
920
921  layoutOptions2: GridLayoutOptions = {
922    regularSize: [1, 1],
923    irregularIndexes: [0, 7], // The number of columns occupied by the grid item whose indexes are 0 and 7 is specified by onGetIrregularSizeByIndex.
924    onGetIrregularSizeByIndex: (index: number) => {
925      if (index === 0) {
926        return [1, 5]
927      }
928      return [1, index % 6 + 1]
929    }
930  }
931
932  build() {
933    Column({ space: 5 }) {
934      Grid(this.scroller, this.layoutOptions1) {
935        ForEach(this.numbers, (day: string) => {
936          ForEach(this.numbers, (day: string) => {
937            GridItem() {
938              Text(day)
939                .fontSize(16)
940                .backgroundColor(0xF9CF93)
941                .width('100%')
942                .height(80)
943                .textAlign(TextAlign.Center)
944            }.selectable(false)
945          }, (day: string) => day)
946        }, (day: string) => day)
947      }
948      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
949      .columnsGap(10)
950      .rowsGap(10)
951      .multiSelectable(true)
952      .scrollBar(BarState.Off)
953      .width('90%')
954      .backgroundColor(0xFAEEE0)
955      .height(300)
956
957      Text('scroll').fontColor(0xCCCCCC).fontSize(9).width('90%')
958      // The grid does not scroll, and undefined is used to reserve space.
959      Grid(undefined, this.layoutOptions2) {
960        ForEach(this.numbers, (day: string) => {
961          ForEach(this.numbers, (day: string) => {
962            GridItem() {
963              Text(day)
964                .fontSize(16)
965                .backgroundColor(0xF9CF93)
966                .width('100%')
967                .height(80)
968                .textAlign(TextAlign.Center)
969            }
970          }, (day: string) => day)
971        }, (day: string) => day)
972      }
973      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
974      .columnsGap(10)
975      .rowsGap(10)
976      .scrollBar(BarState.Off)
977      .width('90%')
978      .backgroundColor(0xFAEEE0)
979      .height(300)
980    }.width('100%').margin({ top: 5 })
981  }
982}
983```
984
985![gridLayoutOptions](figures/gridLayoutOptions.gif)
986
987### Example 4
988
989Example of using **nestedScroll** and **onScrollFrameBegin**:
990
991```ts
992@Entry
993@Component
994struct GridExample {
995  @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
996  @State numbers: number[] = []
997  @State translateY: number = 0
998  private scroller: Scroller = new Scroller()
999  private gridScroller: Scroller = new Scroller()
1000  private touchDown: boolean = false
1001  private listTouchDown: boolean = false
1002  private scrolling: boolean = false
1003
1004  aboutToAppear() {
1005    for (let i = 0; i < 100; i++) {
1006      this.numbers.push(i)
1007    }
1008  }
1009
1010  build() {
1011    Stack() {
1012      Column() {
1013        Row() {
1014          Text('Head')
1015        }
1016
1017        Column() {
1018          List({ scroller: this.scroller }) {
1019            ListItem() {
1020              Grid() {
1021                GridItem() {
1022                  Text('GoodsTypeList1')
1023                }
1024                .backgroundColor(this.colors[0])
1025                .columnStart(0)
1026                .columnEnd(1)
1027
1028                GridItem() {
1029                  Text('GoodsTypeList2')
1030                }
1031                .backgroundColor(this.colors[1])
1032                .columnStart(0)
1033                .columnEnd(1)
1034
1035                GridItem() {
1036                  Text('GoodsTypeList3')
1037                }
1038                .backgroundColor(this.colors[2])
1039                .columnStart(0)
1040                .columnEnd(1)
1041
1042                GridItem() {
1043                  Text('GoodsTypeList4')
1044                }
1045                .backgroundColor(this.colors[3])
1046                .columnStart(0)
1047                .columnEnd(1)
1048
1049                GridItem() {
1050                  Text('GoodsTypeList5')
1051                }
1052                .backgroundColor(this.colors[4])
1053                .columnStart(0)
1054                .columnEnd(1)
1055              }
1056              .scrollBar(BarState.Off)
1057              .columnsGap(15)
1058              .rowsGap(10)
1059              .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
1060              .columnsTemplate('1fr')
1061              .width('100%')
1062              .height(200)
1063            }
1064
1065            ListItem() {
1066              Grid(this.gridScroller) {
1067                ForEach(this.numbers, (item: number) => {
1068                  GridItem() {
1069                    Text(item + '')
1070                      .fontSize(16)
1071                      .backgroundColor(0xF9CF93)
1072                      .width('100%')
1073                      .height('100%')
1074                      .textAlign(TextAlign.Center)
1075                  }
1076                  .width('100%')
1077                  .height(40)
1078                  .shadow({ radius: 10, color: '#909399', offsetX: 1, offsetY: 1 })
1079                  .borderRadius(10)
1080                  .translate({ x: 0, y: this.translateY })
1081                }, (item: string) => item)
1082              }
1083              .columnsTemplate('1fr 1fr')
1084              .friction(0.3)
1085              .columnsGap(15)
1086              .rowsGap(10)
1087              .scrollBar(BarState.Off)
1088              .width('100%')
1089              .height('100%')
1090              .layoutDirection(GridDirection.Column)
1091              .nestedScroll({
1092                scrollForward: NestedScrollMode.PARENT_FIRST,
1093                scrollBackward: NestedScrollMode.SELF_FIRST
1094              })
1095              .onTouch((event: TouchEvent) => {
1096                if (event.type == TouchType.Down) {
1097                  this.listTouchDown = true
1098                } else if (event.type == TouchType.Up) {
1099                  this.listTouchDown = false
1100                }
1101              })
1102            }
1103          }
1104          .scrollBar(BarState.Off)
1105          .edgeEffect(EdgeEffect.None)
1106          .onTouch((event: TouchEvent) => {
1107            if (event.type == TouchType.Down) {
1108              this.touchDown = true
1109            } else if (event.type == TouchType.Up) {
1110              this.touchDown = false
1111            }
1112          })
1113          .onScrollFrameBegin((offset: number, state: ScrollState) => {
1114            if (this.scrolling && offset > 0) {
1115              let newOffset = this.scroller.currentOffset().yOffset
1116              if (newOffset >= 590) {
1117                this.gridScroller.scrollBy(0, offset)
1118                return { offsetRemain: 0 }
1119              } else if (newOffset + offset > 590) {
1120                this.gridScroller.scrollBy(0, newOffset + offset - 590)
1121                return { offsetRemain: 590 - newOffset }
1122              }
1123            }
1124            return { offsetRemain: offset }
1125          })
1126          .onScrollStart(() => {
1127            if (this.touchDown && !this.listTouchDown) {
1128              this.scrolling = true
1129            }
1130          })
1131          .onScrollStop(() => {
1132            this.scrolling = false
1133          })
1134        }
1135        .width('100%')
1136        .height('100%')
1137        .padding({ left: 10, right: 10 })
1138      }
1139
1140      Row() {
1141        Text('Top')
1142          .width(30)
1143          .height(30)
1144          .borderRadius(50)
1145      }
1146      .padding(5)
1147      .borderRadius(50)
1148      .backgroundColor('#ffffff')
1149      .shadow({ radius: 10, color: '#909399', offsetX: 1, offsetY: 1 })
1150      .margin({ right: 22, bottom: 15 })
1151      .onClick(() => {
1152        this.scroller.scrollTo({ xOffset: 0, yOffset: 0 })
1153        this.gridScroller.scrollTo({ xOffset: 0, yOffset: 0 })
1154      })
1155    }
1156    .align(Alignment.BottomEnd)
1157  }
1158}
1159```
1160
1161![nestedScrollExample4](figures/nestedScrollExample4.gif)
1162
1163### Example 5
1164
11651.  Set **editMode\(true\)** to enable edit mode, where the user can drag the grid items.
11662.  Through [onItemDragStart](#events), set the image to be displayed during dragging.
11673.  Through [onItemDrop](#events), obtain the initial position of the dragged item and the position to which the dragged item will be dropped. Through [onItemDrop](#events), complete the array position exchange logic.
1168
1169> **NOTE**
1170>
1171> The drag and drop action is not displayed in the preview.
1172
1173```ts
1174@Entry
1175@Component
1176struct GridExample {
1177  @State numbers: string[] = []
1178  scroller: Scroller = new Scroller()
1179  @State text: string = 'drag'
1180
1181  @Builder pixelMapBuilder () { // Style for the drag event.
1182    Column() {
1183      Text(this.text)
1184        .fontSize(16)
1185        .backgroundColor(0xF9CF93)
1186        .width(80)
1187        .height(80)
1188        .textAlign(TextAlign.Center)
1189    }
1190  }
1191
1192  aboutToAppear() {
1193    for (let i = 1;i <= 15; i++) {
1194      this.numbers.push(i + '')
1195    }
1196  }
1197
1198  changeIndex(index1: number, index2: number) { // Exchange the array position.
1199    let temp: string;
1200    temp = this.numbers[index1];
1201    this.numbers[index1] = this.numbers[index2];
1202    this.numbers[index2] = temp;
1203  }
1204
1205  build() {
1206    Column({ space: 5 }) {
1207      Grid(this.scroller) {
1208        ForEach(this.numbers, (day: string) => {
1209          GridItem() {
1210            Text(day)
1211              .fontSize(16)
1212              .backgroundColor(0xF9CF93)
1213              .width(80)
1214              .height(80)
1215              .textAlign(TextAlign.Center)
1216          }
1217        })
1218      }
1219      .columnsTemplate('1fr 1fr 1fr')
1220      .columnsGap(10)
1221      .rowsGap(10)
1222      .width('90%')
1223      .backgroundColor(0xFAEEE0)
1224      .height(300)
1225      .editMode(true) // Enable edit mode, where the user can drag the grid items.
1226      .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { // Triggered when a grid item starts to be dragged.
1227        this.text = this.numbers[itemIndex]
1228        return this.pixelMapBuilder() // Set the image to be displayed during dragging.
1229      })
1230      .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { // Triggered when the dragged item is dropped on the drop target of the grid.
1231        // If isSuccess is set to false, the item is dropped outside of the grid. If the value of insertIndex is greater than that of length, an item adding event occurs.
1232        if (!isSuccess || insertIndex >= this.numbers.length) {
1233          return
1234        }
1235        console.info('beixiang' + itemIndex + '', insertIndex + '') // itemIndex indicates the initial position of the dragged item. insertIndex indicates the position to which the dragged item will be dropped.
1236        this.changeIndex(itemIndex, insertIndex)
1237      })
1238    }.width('100%').margin({ top: 5 })
1239  }
1240}
1241```
1242
1243Below are some examples.
1244
1245Below shows how the grid looks when dragging of grid items starts.
1246
1247![gridDrag](figures/gridDrag.png)
1248
1249Below shows how the grid looks when dragging of grid items is in progress.
1250
1251![gridDrag](figures/gridDrag1.png)
1252
1253Below shows how the grid looks after grid item 1 and grid item 6 swap their positions.
1254
1255![gridDrag](figures/gridDrag2.png)
1256
1257### Example 6
1258
1259Example of using **layoutDirection**, **maxcount**, **minCount**, and **cellLength**:
1260
1261```ts
1262@Entry
1263@Component
1264struct GridExample {
1265  @State numbers: string[] = []
1266
1267  aboutToAppear() {
1268    for (let i = 1; i <= 30; i++) {
1269      this.numbers.push(i + '')
1270    }
1271  }
1272
1273  build() {
1274    Scroll() {
1275      Column({ space: 5 }) {
1276        Blank()
1277        Text ('The layoutDirection, maxcount, minCount, and cellLength parameters take effect only when neither rowsTemplate nor columnsTemplate is set.')
1278          .fontSize(15).fontColor(0xCCCCCC).width('90%')
1279        Grid() {
1280          ForEach(this.numbers, (day: string) => {
1281            GridItem() {
1282              Text(day).fontSize(16).backgroundColor(0xF9CF93)
1283            }.width(40).height(80).borderWidth(2).borderColor(Color.Red)
1284          }, (day: string) => day)
1285        }
1286        .height(300)
1287        .columnsGap(10)
1288        .rowsGap(10)
1289        .backgroundColor(0xFAEEE0)
1290        .maxCount(6)
1291        .minCount(2)
1292        .cellLength(0)
1293        .layoutDirection(GridDirection.Row)
1294      }
1295      .width('90%').margin({ top: 5, left: 5, right: 5 })
1296      .align(Alignment.Center)
1297    }
1298  }
1299}
1300```
1301
1302![cellLength](figures/cellLength.gif)
1303
1304### Example 7
1305
1306This example demonstrates how to adjust the number of columns in the grid with a pinch gesture using two fingers.
1307
1308```ts
1309// xxx.ets
1310@Entry
1311@Component
1312struct GridExample {
1313  @State numbers: String[] = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19']
1314  @State columns: number = 2
1315
1316  aboutToAppear() {
1317    let lastCount = AppStorage.get<number>('columnsCount')
1318    if (typeof lastCount != 'undefined') {
1319      this.columns = lastCount
1320    }
1321  }
1322
1323  build() {
1324    Column({ space: 5 }) {
1325      Row() {
1326        Text('Pinch to change the number of columns')
1327          .height('5%')
1328          .margin({ top: 10, left: 20 })
1329      }
1330
1331      Grid() {
1332        ForEach(this.numbers, (day: string) => {
1333          ForEach(this.numbers, (day: string) => {
1334            GridItem() {
1335              Text(day)
1336                .fontSize(16)
1337                .backgroundColor(0xF9CF93)
1338                .width('100%')
1339                .height(80)
1340                .textAlign(TextAlign.Center)
1341            }
1342          }, (day: string) => day)
1343        }, (day: string) => day)
1344      }
1345      .columnsTemplate('1fr '.repeat(this.columns))
1346      .columnsGap(10)
1347      .rowsGap(10)
1348      .width('90%')
1349      .scrollBar(BarState.Off)
1350      .backgroundColor(0xFAEEE0)
1351      .height('100%')
1352      .cachedCount(3)
1353      // Switching the number of columns triggers a reordering animation for the item positions.
1354      .animation({
1355        duration: 300,
1356        curve: Curve.Smooth
1357      })
1358      .priorityGesture(
1359        PinchGesture()
1360          .onActionEnd((event: GestureEvent) => {
1361            console.info('end scale:' + event.scale)
1362            // 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.
1363            if (event.scale > 2) {
1364              this.columns--
1365            } else if (event.scale < 0.6) {
1366              this.columns++
1367            }
1368            // 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.
1369            this.columns = Math.min(4, Math.max(1, this.columns));
1370            AppStorage.setOrCreate<number>('columnsCount', this.columns)
1371          })
1372      )
1373    }.width('100%').margin({ top: 5 })
1374  }
1375}
1376```
1377
1378![pinch](figures/grid-pinch.gif)
1379
1380### Example 8
1381This example shows the usage of **auto-fill**, **auto-fit**, and **auto-stretch** in the [columnsTemplate](#columnstemplate) attribute.
1382
1383```ts
1384@Entry
1385@Component
1386struct GridColumnsTemplate {
1387  data: number[] = [0, 1, 2, 3, 4, 5]
1388  data1: number[] = [0, 1, 2, 3, 4, 5]
1389  data2: number[] = [0, 1, 2, 3, 4, 5]
1390
1391  build() {
1392    Column({ space: 10 }) {
1393      Text('auto-fill auto-calculates the number of columns based on the set column width').width('90%')
1394      Grid() {
1395        ForEach(this.data, (item: number) => {
1396          GridItem() {
1397            Text('N' + item).height(80)
1398          }
1399          .backgroundColor(Color.Orange)
1400        })
1401      }
1402      .width('90%')
1403      .border({ width: 1, color: Color.Black })
1404      .columnsTemplate('repeat(auto-fill, 70)')
1405      .columnsGap(10)
1406      .rowsGap(10)
1407      .height(150)
1408
1409      Text('auto-fit calculates the number of columns based on the specified column width, and then any remaining space is evenly distributed across all columns').width('90%')
1410      Grid() {
1411        ForEach(this.data1, (item: number) => {
1412          GridItem() {
1413            Text('N' + item).height(80)
1414          }
1415          .backgroundColor(Color.Orange)
1416        })
1417      }
1418      .width('90%')
1419      .border({ width: 1, color: Color.Black })
1420      .columnsTemplate('repeat(auto-fit, 70)')
1421      .columnsGap(10)
1422      .rowsGap(10)
1423      .height(150)
1424
1425      Text('auto-stretch calculates the number of columns based on the specified column width, and then any remaining space is evenly distributed into the gaps between columns').width('90%')
1426      Grid() {
1427        ForEach(this.data2, (item: number) => {
1428          GridItem() {
1429            Text('N' + item).height(80)
1430          }
1431          .backgroundColor(Color.Orange)
1432        })
1433      }
1434      .width('90%')
1435      .border({ width: 1, color: Color.Black })
1436      .columnsTemplate('repeat(auto-stretch, 70)')
1437      .columnsGap(10)
1438      .rowsGap(10)
1439      .height(150)
1440    }
1441    .width('100%')
1442    .height('100%')
1443  }
1444}
1445```
1446
1447![gridColumnsTemplate](figures/gridColumnsTemplate.png)
1448
1449### Example 9
1450This example implements a grid that contains two columns. The grid item in each column consists of two **Column** components with determined heights and one **Text** component with an undetermined height.
1451
1452By default, the heights of the left and right grid items may differ; however, after the grid's **alignItems** attribute is set to **GridItemAlignment.STRETCH**, the grid item with a shorter height in a row will adopt the height of the taller grid item, aligning their heights within the same row.
1453
1454```ts
1455@Entry
1456@Component
1457struct Index {
1458  @State data: number[] = [];
1459  @State items: number[] = [];
1460
1461  aboutToAppear(): void {
1462    for (let i = 0; i < 100; i++) {
1463      this.data.push(i)
1464      this.items.push(this.getSize())
1465    }
1466  }
1467
1468  getSize() {
1469    let ret = Math.floor(Math.random() * 5)
1470    return Math.max(1, ret)
1471  }
1472
1473  build() {
1474    Column({ space: 10 }) {
1475      Text('Grid alignItems sample code')
1476
1477      Grid() {
1478        ForEach(this.data, (item: number) => {
1479          // GridItem and Column components, when left without explicitly set heights, will by default adapt to the size of their child components. With alignItems set to STRETCH, they will instead take on the height of the tallest component in the current row.
1480          // If the height is explicitly set, the component maintains the defined height and will not follow the height of the tallest component in the current row.
1481          GridItem() {
1482            Column() {
1483              Column().height(100).backgroundColor('#D5D5D5').width('100%')
1484              // The Text component in the center is set with flexGrow(1) to automatically fill the available space within the parent component.
1485              Text('A piece of text.'.repeat(this.items[item]))
1486                .flexGrow(1).width('100%').align(Alignment.TopStart)
1487                .backgroundColor('#F7F7F7')
1488              Column().height(50).backgroundColor('#707070').width('100%')
1489            }
1490          }
1491          .border({ color: Color.Black, width: 1 })
1492        })
1493      }
1494      .columnsGap(10)
1495      .rowsGap(5)
1496      .columnsTemplate('1fr 1fr')
1497      .width('80%')
1498      .height('100%')
1499      // When the grid has its alignItems attribute set to STRETCH, it adjusts the height of all grid items in a row to match the height of the tallest grid item in that row.
1500      .alignItems(GridItemAlignment.STRETCH)
1501      .scrollBar(BarState.Off)
1502    }
1503    .height('100%')
1504    .width('100%')
1505  }
1506}
1507
1508```
1509![gridAlignItems](figures/gridAlignItems.png)
1510