• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
12The **\<Grid>** component accepts only **\<[GridItem](ts-container-griditem.md)>** as its child components.
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** or **LazyForEach** statement, the indexes of all expanded subnodes are calculated.
23>
24>  If the values of [if/else](../../quick-start/arkts-rendering-control-ifelse.md), [ForEach](../../quick-start/arkts-rendering-control-foreach.md), and [LazyForEach](../../quick-start/arkts-rendering-control-lazyforeach.md) change, the indexes of subnodes 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**Parameters**
39
40| Name  | Type                                   | Mandatory| Description                                                    |
41| -------- | ------------------------------------------- | ---- | ------------------------------------------------------------ |
42| 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).|
43| layoutOptions<sup>10+</sup> | [GridLayoutOptions](#gridlayoutoptions10) | No| Layout options of a scrolling grid.|
44
45## GridLayoutOptions<sup>10+</sup>
46
47Defines 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 for the 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 4.
48
49**Parameters**
50| Name   | Type     | Mandatory  | Description                   |
51| ----- | ------- | ---- | --------------------- |
52| 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.  |
53| 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.|
54| 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**. A grid item cannot occupy multiple rows in vertical scrolling mode, or multiple columns in horizontal scrolling mode.|
55| onGetRectByIndex<sup>11+</sup> | (index: number) => [number, number,number,number] | No |  Position and size [rowStart,columnStart,rowSpan,columnSpan] of the grid item with the specified index. |
56
57## Attributes
58
59In addition to the [universal attributes](ts-universal-attributes-size.md), the following attributes are supported.
60
61| Name| Type| Description|
62| -------- | -------- | -------- |
63| columnsTemplate | string | Number of columns or minimum column width in the grid. If this attribute is not set, one column will be used.<br>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.<br>**columnsTemplate('repeat(auto-fit, track-size)')** sets the minimum column width to **track-size**, based on which the number of columns and the actual column width are automatically obtained.<br>**columnsTemplate('repeat(auto-fill, track-size)')** sets the fixed column width to **track-size**, based on which the number of columns is automatically obtained.<br>**repeat**, **auto-fit**, and **auto-fill** are keywords. **track-size** indicates the column width, in the unit of px, vp, %, or any valid digit. The value must be greater than or equal to one valid column width.<br>**NOTE**<br>If 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.|
64| rowsTemplate | string | Number of rows or minimum row height in the grid. If this attribute is not set, one row will be used.<br>For 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.<br>**rowsTemplate('repeat(auto-fit, track-size)')** sets the minimum row height to **track-size**, based on which the number of rows and the actual row height are automatically obtained.<br>**rowsTemplate('repeat(auto-fill, track-size)')** sets the fixed row height to **track-size**, based on which the number of rows is automatically obtained.<br>**repeat**, **auto-fit**, and **auto-fill** are keywords. **track-size** indicates the row height, in the unit of px, vp, %, or any valid digit. The value must be greater than or equal to one valid row height.<br>**NOTE**<br>If 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.|
65| columnsGap | [Length](ts-types.md#length) | Gap between columns.<br>Default value: **0**<br>**NOTE**<br>A value less than 0 evaluates to the default value.|
66| rowsGap | [Length](ts-types.md#length) | Gap between rows.<br>Default value: **0**<br>**NOTE**<br>A value less than 0 evaluates to the default value.|
67| scrollBar      | [BarState](ts-appendix-enums.md#barstate) | Scrollbar status.<br>Default value: **BarState.Off**<br>**NOTE**<br>In API version 9 and earlier versions, the default value is **BarState.Off**. In API version 10, the default value is **BarState.Auto**.|
68| scrollBarColor | string \| number \| [Color](ts-appendix-enums.md#color) | Color of the scrollbar.|
69| scrollBarWidth | string \| number    | Width of the scrollbar. After the width is set, the scrollbar is displayed with the set width in normal state and pressed state.<br>Default value: **4**<br>Unit: vp|
70| cachedCount | number                                   | Number of grid items to be preloaded (cached). It works only in [LazyForEach](../../quick-start/arkts-rendering-control-lazyforeach.md). For details, see [Minimizing White Blocks During Swiping](../../performance/arkts-performance-improvement-recommendation.md#minimizing-white-blocks-during-swiping).<br>Default value: **1**<br>**NOTE**<br>The 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.<br>Grid items that exceed the display and cache range are released.<br>A value less than 0 evaluates to the default value.|
71| editMode <sup>8+</sup>                   | boolean | Whether to enter editing mode. In editing mode, the user can drag the **\<[GridItem](ts-container-griditem.md)>** in the **\<Grid>** component.<br>Default value: **false**|
72| layoutDirection<sup>8+</sup>             | [GridDirection](#griddirection8) | Main axis direction of the grid.<br>Default value: **GridDirection.Row**|
73| maxCount<sup>8+</sup> | number  | When **layoutDirection** is **Row** or **RowReverse**: maximum number of columns that can be displayed.<br>When **layoutDirection** is **Column** or **ColumnReverse**: maximum number of rows that can be displayed.<br>Default value: **Infinity**<br>**NOTE**<br>If the value of **maxCount** is smaller than that of **minCount**, the default values of **maxCount** and **minCount** are used.<br>A value less than 1 evaluates to the default value.|
74| minCount<sup>8+</sup> | number  | When **layoutDirection** is **Row** or **RowReverse**: minimum number of columns that can be displayed.<br>When **layoutDirection** is **Column** or **ColumnReverse**: minimum number of rows that can be displayed.<br>Default value: **1**<br>**NOTE**<br>A value less than 1 evaluates to the default value.|
75| cellLength<sup>8+</sup> | number  | When **layoutDirection** is **Row** or **RowReverse**: fixed height per row.<br>When **layoutDirection** is **Column** or **ColumnReverse**: fixed width per column.<br>Default value: size of the first element|
76| multiSelectable<sup>8+</sup> | boolean | Whether to enable mouse frame selection.<br>Default value: **false**<br>- **false**: The mouse frame selection is disabled.<br>- **true**: The mouse frame selection is enabled.<br>**NOTE**<br> When mouse frame selection is enabled, you can use the **selected** attribute and the **onSelect** event of the **\<Griditem>** component to obtain the selection status of the component; you can also set the [style](./ts-universal-attributes-polymorphic-style.md) of the component in the selected state (by default, no style is set for the selected state).|
77| supportAnimation<sup>8+</sup> | boolean | Whether to enable animation. Currently, the grid item drag animation is supported.<br>Default value: **false**<br>**NOTE**<br> Animation is supported only in scrolling mode (only **rowsTemplate** or **columnsTemplate** is set).|
78| edgeEffect<sup>10+</sup> | value:[EdgeEffect](ts-appendix-enums.md#edgeeffect), <br>options?:[EdgeEffectOptions<sup>11+</sup>](ts-container-scroll.md#edgeeffectoptions11) | Effect used at the edges of the component when the boundary of the scrollable content is reached.<br>\- **value**: effect used at the edges of the **\<Grid>** component when the boundary of the scrollable content is reached. The spring effect and shadow effect are supported.<br>Default value: **EdgeEffect.None**<br>\- **options**: whether to enable the scroll effect when the component content size is smaller than the component itself.<br>Default value: **false**|
79| enableScrollInteraction<sup>10+</sup>  |  boolean  |   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.<br>Default value: **true**     |
80| nestedScroll<sup>10+</sup>                 | [NestedScrollOptions](ts-container-scroll.md#nestedscrolloptions10)         | Nested scrolling options. You can set the nested scrolling mode in the forward and backward directions to implement scrolling linkage with the parent component.|
81| friction<sup>10+</sup> | number \| [Resource](ts-types.md#resource)    | Friction coefficient. It applies only to gestures in the scrolling area, and it affects only indirectly the scroll chaining during the inertial scrolling process.<br>Default value: **0.9** for wearable devices and **0.6** for non-wearable devices<br>**NOTE**<br>A value less than or equal to 0 evaluates to the default value.|
82
83Depending on the settings of the **rowsTemplate** and **columnsTemplate** attributes, the **\<Grid>** component supports the following layout modes:
84
851. **rowsTemplate** and **columnsTemplate** are both set
86
87- The **\<Grid>** component displays only elements in a fixed number of rows and columns and cannot be scrolled.
88- In this mode, the following attributes do not take effect: **layoutDirection**, **maxCount**, **minCount**, and **cellLength**.
89- If the width and height of a grid are not set, the grid adapts to the size of its parent component by default.
90- 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.
91- By default, the grid items fill the entire grid.
92
932. Either **rowsTemplate** or **columnsTemplate** is set
94
95- The **\<Grid>** component arranges elements in the specified direction and allows for scrolling to display excess elements.
96- If **columnsTemplate** is set, the component scrolls vertically, the main axis runs vertically, and the cross axis runs horizontally.
97- If **rowsTemplate** is set, the component scrolls horizontally, the main axis runs horizontally, and the cross axis runs vertically.
98- In this mode, the following attributes do not take effect: **layoutDirection**, **maxCount**, minCount, and **cellLength**.
99- 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.
100- The main axis size of the grid is the maximum height of all grid items in the cross axis direction of the current grid.
101
1023. Neither **rowsTemplate** nor **columnsTemplate** is set
103
104- 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**.
105- 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.
106- In this mode, only the following attributes take effect: **layoutDirection**, **maxCount**, **minCount**, **cellLength**, **editMode**, **columnsGap**, and **rowsGap**.
107- 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.
108- 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.
109
110## GridDirection<sup>8+</sup>
111
112| Name  |Value| Description                                  |
113| ------ |------| -------------------------------------- |
114| Row  |  0  | Horizontal layout, where the child components are arranged from left to right as the main axis runs along the rows.|
115| Column |  1  | Vertical layout, where the child components are arranged from top to bottom as the main axis runs down the columns.|
116| RowReverse    |  2  | Reverse horizontal layout, where the child components are arranged from right to left as the main axis runs along the rows.|
117| ColumnReverse   |  3  | Reverse vertical layout, where the child components are arranged from bottom up as the main axis runs down the columns.|
118
119> **NOTE**
120>
121> The default value of the universal attribute [clip](ts-universal-attributes-sharp-clipping.md) is **true** for the **\<Grid>** component.
122
123## Events
124
125In addition to the [universal events](ts-universal-events-click.md), the following events are supported.
126
127| Name| Description|
128| -------- | -------- |
129| onScrollIndex(event: (first: number, last<sup>10+</sup>: number) => void) | Triggered when the first or last item displayed in the grid changes. It is triggered once when the grid is initialized.<br>- **first**: index of the first item of the grid.<br>- **last**: index of the last item of the grid.<br>This event is triggered when either of the preceding indexes changes.|
130| onItemDragStart<sup>8+</sup>(event: (event: ItemDragInfo, itemIndex: number) => (() => any) \| void) | Triggered when a grid item starts to be dragged.<br>- **event**: See [ItemDragInfo](#itemdraginfo).<br>- **itemIndex**: index of the dragged item.<br>**NOTE**<br>If **void** is returned, the drag operation cannot be performed.<br>This event is triggered when the user long presses a grid item.<br>Drag detection also requires long press, and the event processing mechanism preferentially triggers child component events. Therefore, when **LongPressGesture** is bound to the grid item, the drag operation cannot be performed. In light of this, if both long press and drag operations are required, you can use universal drag events.|
131| onItemDragEnter<sup>8+</sup>(event: (event: ItemDragInfo) => void) | Triggered when the dragged item enters the drop target of the grid.<br>- **event**: See [ItemDragInfo](#itemdraginfo).|
132| onItemDragMove<sup>8+</sup>(event: (event: ItemDragInfo, itemIndex: number, insertIndex: number) => void) | Triggered when the dragged item moves over the drop target of the grid.<br>- **event**: See [ItemDragInfo](#itemdraginfo).<br>- **itemIndex**: initial position of the dragged item.<br>- **insertIndex**: index of the position to which the dragged item will be dropped.|
133| onItemDragLeave<sup>8+</sup>(event: (event: ItemDragInfo, itemIndex: number) => void) | Triggered when the dragged item leaves the drop target of the grid.<br>- **event**: See [ItemDragInfo](#itemdraginfo).<br>- **itemIndex**: index of the dragged item.|
134| onItemDrop<sup>8+</sup>(event: (event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => void) | Triggered when the dragged item is dropped on the drop target of the grid.<br>- **event**: See [ItemDragInfo](#itemdraginfo).<br>- **itemIndex**: initial position of the dragged item.<br>- **insertIndex**: index of the position to which the dragged item will be dropped.<br>- **isSuccess**: whether the dragged item is successfully dropped.|
135| onScrollBarUpdate<sup>10+</sup>(event: (index: number, offset: number) => ComputedBarAttribute) | Triggered when the first item displayed in the grid changes. You can use this callback to set the position and length of the scrollbar.<br>- **index**: index of the first item displayed in the grid.<br>- **offset**: offset of the displayed first item relative to the start position of the grid.<br>- **ComputedBarAttribute**: See [ComputedBarAttribute](#computedbarattribute). |
136| onScroll<sup>10+</sup>(event: (scrollOffset: number, scrollState: [ScrollState](ts-container-list.md#scrollstate)) => void) | Triggered when the grid scrolls.<br>- **scrollOffset**: scroll offset of each frame. The offset is positive when the grid is scrolled up and negative when the list is scrolled down.<br>- **scrollState**: current scroll state.|
137| onReachStart<sup>10+</sup>(event: () => void)          | Triggered when the grid reaches the start position.<br>**NOTE**<br>This event is triggered once when the grid is initialized and once when the grid scrolls to the start position. When the grid's edge effect is the spring effect, this event is triggered once when the grid passes the start position and is triggered again when the grid returns to the start position.|
138| onReachEnd<sup>10+</sup>(event: () => void)            | Triggered when the grid reaches the end position.<br>**NOTE**<br>When the grid's edge effect is the spring effect, this event is triggered once when the grid passes the end position and is triggered again when the grid returns to the end position.|
139| onScrollFrameBegin<sup>10+</sup>(event: (offset: number, state: ScrollState) => { offsetRemain: number }) | Triggered when the grid starts to scroll. The input parameters indicate the amount by which the grid will scroll. The event handler then works out the amount by which the grid needs to scroll based on the real-world situation and returns the result.<br>\- **offset**: amount to scroll by, in vp.<br>\- **state**: current scrolling state.<br>- **offsetRemain**: actual amount by which the grid scrolls, in vp.<br>This event is triggered when the user starts dragging the grid or the grid starts inertial scrolling. This event is not triggered when the grid rebounds or the scrolling controller is used.<br>**NOTE**<br>If **gridDirection** is set to **Axis.Vertical**, the return value is the amount by which the grid needs to scroll in the vertical direction. If **gridDirection** is set to **Axis.Horizontal**, the return value is the amount by which the grid needs to scroll in the horizontal direction.|
140| onScrollStart<sup>10+</sup>(event: () => void) | Triggered 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.|
141| onScrollStop<sup>10+</sup>(event: () => void)          | Triggered 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.|
142
143## ItemDragInfo
144
145| Name        | Type        |   Description        |
146| ---------- | ---------- | ---------- |
147| x | number |  X coordinate of the dragged item.   |
148| y   | number |  Y coordinate of the dragged item.   |
149
150## ComputedBarAttribute
151
152| Name        | Type        |   Description        |
153| ---------- | ---------- | ---------- |
154| totalOffset | number |  Total offset of the grid content relative to the display area.   |
155| totalLength   | number |  Total length of the grid content.   |
156
157## Example
158
159### Example 1
160
161```ts
162// xxx.ets
163@Entry
164@Component
165struct GridExample {
166  @State numbers: String[] = ['0', '1', '2', '3', '4']
167  scroller: Scroller = new Scroller()
168
169  build() {
170    Column({ space: 5 }) {
171      Grid() {
172        ForEach(this.numbers, (day: string) => {
173          ForEach(this.numbers, (day: string) => {
174            GridItem() {
175              Text(day)
176                .fontSize(16)
177                .backgroundColor(0xF9CF93)
178                .width('100%')
179                .height('100%')
180                .textAlign(TextAlign.Center)
181            }
182          }, (day: string) => day)
183        }, (day: string) => day)
184      }
185      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
186      .rowsTemplate('1fr 1fr 1fr 1fr 1fr')
187      .columnsGap(10)
188      .rowsGap(10)
189      .width('90%')
190      .backgroundColor(0xFAEEE0)
191      .height(300)
192
193      Text('scroll').fontColor(0xCCCCCC).fontSize(9).width('90%')
194      Grid(this.scroller) {
195        ForEach(this.numbers, (day: string) => {
196          ForEach(this.numbers, (day: string) => {
197            GridItem() {
198              Text(day)
199                .fontSize(16)
200                .backgroundColor(0xF9CF93)
201                .width('100%')
202                .height(80)
203                .textAlign(TextAlign.Center)
204            }
205          }, (day: string) => day)
206        }, (day: string) => day)
207      }
208      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
209      .columnsGap(10)
210      .rowsGap(10)
211      .friction(0.6)
212      .edgeEffect(EdgeEffect.Spring)
213      .scrollBar(BarState.On)
214      .onScrollIndex((first: number) => {
215        console.info(first.toString())
216      })
217      .width('90%')
218      .backgroundColor(0xFAEEE0)
219      .height(300)
220      Button('next page')
221        .onClick(() => {// Click to go to the next page.
222          this.scroller.scrollPage({ next: true })
223        })
224    }.width('100%').margin({ top: 5 })
225  }
226}
227```
228
229![en-us_image_0000001219744183](figures/en-us_image_0000001219744183.gif)
230
231### Example 2
232
2331.  Set **editMode\(true\)** to enable the grid to enter editing mode, where the user can drag the grid items.
234
2352.  Through [onItemDragStart](#events), set the image to be displayed during dragging.
236
2373.  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.
238
239```ts
240@Entry
241@Component
242struct GridExample {
243  @State numbers: string[] = []
244  scroller: Scroller = new Scroller()
245  @State text: string = 'drag'
246
247  @Builder pixelMapBuilder () { // Style for the drag event.
248    Column() {
249      Text(this.text)
250        .fontSize(16)
251        .backgroundColor(0xF9CF93)
252        .width(80)
253        .height(80)
254        .textAlign(TextAlign.Center)
255    }
256  }
257
258  aboutToAppear() {
259    for (let i = 1;i <= 15; i++) {
260      this.numbers.push(i + '')
261    }
262  }
263
264  changeIndex(index1: number, index2: number) { // Exchange the array position.
265    let temp: string;
266    temp = this.numbers[index1];
267    this.numbers[index1] = this.numbers[index2];
268    this.numbers[index2] = temp;
269  }
270
271  build() {
272    Column({ space: 5 }) {
273      Grid(this.scroller) {
274        ForEach(this.numbers, (day: string) => {
275          GridItem() {
276            Text(day)
277              .fontSize(16)
278              .backgroundColor(0xF9CF93)
279              .width(80)
280              .height(80)
281              .textAlign(TextAlign.Center)
282          }
283        })
284      }
285      .columnsTemplate('1fr 1fr 1fr')
286      .columnsGap(10)
287      .rowsGap(10)
288      .onScrollIndex((first: number) => {
289        console.info(first.toString())
290      })
291      .width('90%')
292      .backgroundColor(0xFAEEE0)
293      .height(300)
294      .editMode(true) // Enable the grid to enter editing mode, where the user can drag the grid items.
295      .onItemDragStart((event: ItemDragInfo, itemIndex: number) => { // Triggered when a grid item starts to be dragged.
296        this.text = this.numbers[itemIndex]
297        return this.pixelMapBuilder() // Set the image to be displayed during dragging.
298      })
299      .onItemDrop((event: ItemDragInfo, itemIndex: number, insertIndex: number, isSuccess: boolean) => { // Triggered when the dragged item is dropped on the drop target of the grid.
300        // 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.
301        if (!isSuccess || insertIndex >= this.numbers.length) {
302          return
303        }
304        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.
305        this.changeIndex(itemIndex, insertIndex)
306      })
307    }.width('100%').margin({ top: 5 })
308  }
309}
310```
311
312Below are some examples.
313
314Below shows how the grid looks when dragging of grid items starts.
315
316![gridDrag](figures/gridDrag.png)
317
318Below shows how the grid looks when dragging of grid items is in progress.
319
320![gridDrag](figures/gridDrag1.png)
321
322Below shows how the grid looks after grid item 1 and grid item 6 swap their positions.
323
324![gridDrag](figures/gridDrag2.png)
325
326### Example 3
327
328This example uses **irregularIndexes** and **onGetIrregularSizeByIndex** in **GridLayoutOptions**.
329
330```ts
331// xxx.ets
332@Entry
333@Component
334struct GridExample {
335  @State numbers: String[] = ['0', '1', '2', '3', '4']
336  scroller: Scroller = new Scroller()
337  layoutOptions1: GridLayoutOptions = {
338    regularSize: [1, 1],        // Only [1, 1] is supported.
339    irregularIndexes: [0, 6], // The grid item whose indexes are 0 and 6 occupies one row.
340  }
341
342  layoutOptions2: GridLayoutOptions = {
343    regularSize: [1, 1],
344    irregularIndexes: [0, 7], // The number of columns occupied by the grid item whose indexes are 0 and 7 is specified by onGetIrregularSizeByIndex.
345    onGetIrregularSizeByIndex: (index: number) => {
346      if (index === 0) {
347        return [1, 5]
348      }
349      return [1, index % 6 + 1]
350    }
351  }
352
353  build() {
354    Column({ space: 5 }) {
355      Grid(this.scroller, this.layoutOptions1) {
356        ForEach(this.numbers, (day: string) => {
357          ForEach(this.numbers, (day: string) => {
358            GridItem() {
359              Text(day)
360                .fontSize(16)
361                .backgroundColor(0xF9CF93)
362                .width('100%')
363                .height(80)
364                .textAlign(TextAlign.Center)
365            }
366          }, (day: string) => day)
367        }, (day: string) => day)
368      }
369      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
370      .columnsGap(10)
371      .rowsGap(10)
372      .scrollBar(BarState.Off)
373      .width('90%')
374      .backgroundColor(0xFAEEE0)
375      .height(300)
376
377      Text('scroll').fontColor(0xCCCCCC).fontSize(9).width('90%')
378      // The grid does not scroll, and undefined is used to reserve space.
379      Grid(undefined, this.layoutOptions2) {
380        ForEach(this.numbers, (day: string) => {
381          ForEach(this.numbers, (day: string) => {
382            GridItem() {
383              Text(day)
384                .fontSize(16)
385                .backgroundColor(0xF9CF93)
386                .width('100%')
387                .height(80)
388                .textAlign(TextAlign.Center)
389            }
390          }, (day: string) => day)
391        }, (day: string) => day)
392      }
393      .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
394      .columnsGap(10)
395      .rowsGap(10)
396      .scrollBar(BarState.Off)
397      .width('90%')
398      .backgroundColor(0xFAEEE0)
399      .height(300)
400    }.width('100%').margin({ top: 5 })
401  }
402}
403```
404
405![gridLayoutOptions](figures/gridLayoutOptions.png)
406
407### Example 4
408
409This example uses **onGetRectByIndex** in **GridLayoutOptions**.
410
411```ts
412@Entry
413@Component
414struct GridExample {
415  @State numbers: String[] = ['0', '1','2','3','4','5']
416
417  layoutOptions3: GridLayoutOptions = {
418    regularSize: [1, 1],
419    onGetRectByIndex: (index: number) => {
420      if (index == 0)
421        return [0, 0, 1, 1]
422      else if(index==1)
423        return [0, 1, 2, 2]
424      else if(index==2)
425        return [0 ,3 ,3 ,3]
426      else if(index==3)
427        return [3, 0, 3, 3]
428      else if(index==4)
429        return [4, 3, 2, 2]
430      else
431        return [5, 5, 1, 1]
432    }
433  }
434
435
436  build() {
437    Column({ space: 5 }) {
438      Text('scroll').fontColor(0xCCCCCC).fontSize(9).width('90%')
439
440      Grid(undefined, this.layoutOptions3) {
441        ForEach(this.numbers, (day: string) => {
442          GridItem() {
443            Text(day)
444              .fontSize(16)
445              .backgroundColor(0xF9CF93)
446              .width('100%')
447              .height("100%")
448              .textAlign(TextAlign.Center)
449          }
450          .height("100%")
451          .width('100%')
452        }, (day: string) => day)
453      }
454      .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
455      .rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr')
456      .columnsGap(10)
457      .rowsGap(10)
458      .scrollBar(BarState.Off)
459      .width('90%')
460      .backgroundColor(0xFAEEE0)
461      .height(300)
462
463    }.width('100%').margin({ top: 5 })
464  }
465}
466
467```
468
469![onGetRectByIndex](figures/onGetRectByIndex.png)
470