• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Creating a Grid (Grid/GridItem)
2
3
4## Overview
5
6The grid layout consists of cells formed by rows and columns. You can specify the cells where items are located to create various layouts. The grid layout excels at dividing a page into regions and defining the proportion of child components. It is a key adaptive layout and applies to scenarios such as photo gallery, calendar, and calculator.
7
8ArkUI provides the [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md) and [GridItem](../reference/apis-arkui/arkui-ts/ts-container-griditem.md) components for building grid layouts. **Grid** is a container for defining the grid layout, while **GridItem** is a child component in the container. The **Grid** component allows creation of child components using methods such as [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).
9
10
11## Layout and Constraints
12
13Each item in the **Grid** container corresponds to a **GridItem** component, as shown below.
14
15  **Figure 1** Relationship between Grid and GridItem components
16![en-us_image_0000001511900472](figures/en-us_image_0000001511900472.png)
17
18>**NOTE**
19>
20>The **Grid** component accepts only **GridItem** as its child.
21
22The grid layout is a two-dimensional layout. The **Grid** component allows you to define the number of rows and columns, proportion of each row and column, number of rows or columns that child components span, and the horizontal and vertical alignment. When it has its size changed, its child components and spacing are adjusted proportionally. By leveraging these layout capabilities, you can build grid layouts of different styles, as shown below.
23
24  **Figure 2** Grid layout
25![en-us_image_0000001562700473](figures/en-us_image_0000001562700473.png)
26
27The size of the **Grid** component follows its width and height settings (if configured) or adapts to the size of its parent component.
28
29Depending on the settings of the quantity and proportion of rows and columns, the **Grid** component behaves as follows:
30
31- If both the quantity and proportion are set for rows or columns, the **Grid** component displays elements only in the set number of rows or columns, and it cannot be scrolled. (This layout mode is recommended.)
32
33- If only the quantity or proportion is set for rows or columns, the **Grid** component lays out elements in the specified direction, and it can be scrolled to display excess elements.
34
35- If neither the quantity nor the proportion is set for rows or columns, the **Grid** component lays out elements in the layout direction. The number of rows and columns is determined by the layout direction and the width and height of the grid. Elements that exceed the range of rows and columns are not displayed, and the **Grid** component cannot be scrolled.
36
37
38## Setting the Arrangement Mode
39
40
41### Setting the Number and Proportion of Rows and Columns
42
43You can set the number and proportion of rows and columns to determine the overall arrangement mode of the grid layout. To do so, use the **rowsTemplate** and **columnsTemplate** attributes of the **Grid** component.
44
45The values of **rowsTemplate** and **columnsTemplate** are a string consisting of 'number+fr' segments, separated by spaces. Wherein **fr** indicates the number of rows or columns in the grid layout, and the number in front of **fr** is used to calculate the proportion of the row or column in the grid width, thereby determining the width of the row or column.
46
47  **Figure 3** Example of the proportion of rows and columns
48![en-us_image_0000001562820833](figures/en-us_image_0000001562820833.png)
49
50The preceding figure shows a grid layout with three rows and three columns. The grid layout is divided into three parts in the vertical direction with each row taking up 1/3, and four parts in the horizontal direction with the first column taking up 1/4, the second column 2/4, and the third column 1/4.
51
52This layout can be implemented by setting **rowsTemplate** to **'1fr 1fr 1fr'** and **columnsTemplate** to **'1fr 2fr 1fr'**.
53
54
55```ts
56Grid() {
57  // ...
58}
59.rowsTemplate('1fr 1fr 1fr')
60.columnsTemplate('1fr 2fr 1fr')
61```
62
63>**NOTE**
64>
65>When **rowsTemplate** or **columnsTemplate** is set for the **Grid** component, its **layoutDirection**, **maxCount**, **minCount**, and **cellLength** attributes do not take effect. For details about the attributes, see [Grid Attributes](../reference/apis-arkui/arkui-ts/ts-container-grid.md#attributes).
66
67
68### Setting the Number of Rows and Columns Occupied by a Child Component
69
70In real-world applications, an uneven grid layout, where grid cells span a varying number of cells and rows, is as common as its even counterpart. To allow a single grid cell in a grid to span multiple rows or columns, passing appropriate [GridLayoutOptions](../reference/apis-arkui/arkui-ts/ts-container-grid.md#gridlayoutoptions10) when creating the grid. Use **irregularIndexes** and **onGetIrregularSizeByIndex** for grids with only **rowsTemplate** or **columnsTemplate**, and **onGetRectByIndex** for grids with both.
71
72  **Figure 4** Uneven grid layout
73
74![en-us_image_0000001511900480](figures/en-us_image_0000001511900480.png)
75
76A common application with an uneven grid layout is the calculator. As shown in the following figure, the **0** key spans the first and second columns, and the **=** key spans the fifth and sixth rows. For a grid layout created using the **Grid** component, the row and column numbers start from 0 and increase incrementally.
77
78  **Figure 5** Calculator
79
80![en-us_image_0000001511421292](figures/en-us_image_0000001511421292.png)
81
82In the grid, use the **onGetRectByIndex** callback to return the array [rowStart, columnStart, rowSpan, columnSpan] to achieve a layout that spans rows and columns, wherein **rowStart** and **rowEnd** indicate the start and end row numbers of the current element, and **columnStart** and **columnEnd** indicate the start and end column numbers of the current element.
83
84To make the **0** key span across the first and second columns, and the **=** key span across the fifth and sixth rows, set **onGetRectByIndex** for **0** and **=** as follows: for **0**, set **rowStart** and **columnStart** at **6** and **0**, and **rowSpan** and **columnSpan** at **1** and **2**; for **=**, set **rowStart** and **columnStart** at **5** and **3**, and **rowSpan** and **columnSpan** at **2** and **1**.
85
86
87```ts
88layoutOptions: GridLayoutOptions = {
89  regularSize: [1, 1],
90  onGetRectByIndex: (index: number) => {
91    if (index = = key1) { // key1 is the index of the 0 key.
92      return [6, 0, 1, 2];
93    } else if (index == key2) { // key2 is the index of the = key.
94      return [5, 3, 2, 1];
95    }
96    // ...
97    // Here, you need to return the positions of other items based on the specific layout.
98  }
99}
100
101Grid(undefined, this.layoutOptions) {
102  // ...
103}
104.columnsTemplate('1fr 1fr 1fr 1fr')
105.rowsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
106```
107
108
109### Setting the Main Axis Direction
110
111When neither the number nor proportion is set for rows and columns in a grid layout, you can use the **layoutDirection** attribute to set the main axis direction and thereby specify the arrangement mode of child components. In addition, you can use the **minCount** and **maxCount** attributes to restrict the number of grid cells along the main axis.
112
113  **Figure 6** Main axis direction
114
115![en-us_image_0000001562700469](figures/en-us_image_0000001562700469.png)
116
117When **layoutDirection** is set to **Row**, child components are arranged from left to right. When a row is full, a new row is added. When **layoutDirection** is set to **Column**, child components are arranged from top to bottom. When a column is full, a new column is added. In this example, the **maxCount** attribute is set to **3**, indicating that the maximum number of grid cells displayed along the main axis is 3.
118
119
120```ts
121Grid() {
122  // ...
123}
124.maxCount(3)
125.layoutDirection(GridDirection.Row)
126```
127
128>**NOTE**
129>
130>- The **layoutDirection** attribute takes effect only when **rowsTemplate** and **columnsTemplate** are not set. In this case, child components are arranged in the direction set by **layoutDirection**.
131>- When only **rowsTemplate** is set, the main axis of the grid runs in the horizontal direction, and the cross axis runs in the vertical direction.
132>- When only **columnsTemplate** is set, the main axis of the grid runs in the vertical direction, and the cross axis runs in the horizontal direction.
133
134
135## Displaying Data in a Grid Layout
136
137The grid layout organizes its internal elements in two-dimensional layout mode, as shown in the following figure.
138
139**Figure 7** General office services
140
141![en-us_image_0000001563060729](figures/en-us_image_0000001563060729.png)
142
143The **Grid** component can display a group of **GridItem** child components in two-dimensional layout mode.
144
145
146```ts
147Grid() {
148  GridItem() {
149    Text('Conference')
150      // ...
151  }
152
153  GridItem() {
154    Text('Sign-in')
155      // ...
156  }
157
158  GridItem() {
159    Text('Vote')
160      // ...
161  }
162
163  GridItem() {
164    Text('Print')
165      // ...
166  }
167}
168.rowsTemplate('1fr 1fr')
169.columnsTemplate('1fr 1fr')
170```
171
172For multiple **GridItem** components with similar content structures, you are advised to nest them in **ForEach** statements to reduce repeated code.
173
174
175```ts
176@Entry
177@Component
178struct OfficeService {
179  @State services: Array<string> = ['Conference', 'Vote','Sign-in', 'Print']
180
181  build() {
182    Column() {
183      Grid() {
184        ForEach(this.services, (service:string) => {
185          GridItem() {
186            Text(service)
187          }
188        }, (service:string):string => service)
189      }
190      .rowsTemplate(('1fr 1fr') as string)
191      .columnsTemplate(('1fr 1fr') as string)
192    }
193  }
194}
195```
196
197
198## Setting the Gap Between Rows and Columns
199
200The horizontal spacing between two grid cells is called row spacing, and the vertical spacing is called column spacing, as shown in the following figure.
201
202**Figure 8** Row spacing and column spacing
203
204![en-us_image_0000001511580908](figures/en-us_image_0000001511580908.png)
205
206You can use **rowsGap** and **columnsGap** to set the row spacing and column spacing of the grid layout. In the calculator shown in Figure 5, the row spacing is 15 vp, and the column spacing is 10vp.
207
208
209```ts
210Grid() {
211  // ...
212}
213.columnsGap(10)
214.rowsGap(15)
215```
216
217
218## Building a Scrollable Grid Layout
219
220The scrollable grid layout is often used on the file list, product list, video list, and similar pages, as shown in the following figure. When only the number or proportion is set for rows and columns, that is, only the **rowsTemplate** or **columnsTemplate** attribute is set, the elements in the grid are arranged in the configured direction. When the content goes beyond the display area, the grid can be scrolled.
221
222**Figure 9** Horizontal scrollable grid layout
223
224![en-us_image_0000001511740512](figures/en-us_image_0000001511740512.gif)
225
226If **columnsTemplate** is set, the grid scrolls vertically. If **rowsTemplate** is set, the grid scrolls horizontally.
227
228In the horizontal scrollable grid layout shown in the preceding figure, **rowsTemplate** is set but **columnsTemplate** is not. When the content exceeds the width of the grid, the grid can scroll horizontally to display the content outside of the display area.
229
230
231```ts
232@Entry
233@Component
234struct Shopping {
235  @State services: Array<string> = ['Live', 'Premium']
236
237  build() {
238    Column({ space: 5 }) {
239      Grid() {
240        ForEach(this.services, (service: string, index) => {
241          GridItem() {
242          }
243          .width('25%')
244        }, (service:string):string => service)
245      }
246      .rowsTemplate('1fr 1fr') // Set only the rowsTemplate attribute. When the content exceeds the display area of the grid, the grid can be scrolled horizontally.
247      .rowsGap(15)
248    }
249  }
250}
251```
252
253
254## Controlling the Scrolling Position
255
256Similar to the Back to top button in a list layout, the feature of controlling the scrolling position is commonly used in the grid layout, for example, page turning in the calendar application, as shown below.
257
258  **Figure 10** Page turning in the calendar application
259
260![en-us_image_0000001562940549](figures/en-us_image_0000001562940549.gif)
261
262When the **Grid** component is initialized, it can be bound to a [Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller) object for scrolling control. In this example, the [scrollPage](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scrollpage9) API of the **Scroller** object is used to turn pages.
263
264
265```ts
266private scroller: Scroller = new Scroller()
267```
268
269On the calendar page, when a user clicks the **Next** button, the application responds to the click event by setting the **next** parameter in the **scrollPage** API to **true** to scroll to the next page.
270
271
272```ts
273Column({ space: 5 }) {
274  Grid(this.scroller) {
275  }
276  .columnsTemplate('1fr 1fr 1fr 1fr 1fr 1fr 1fr')
277
278  Row({space: 20}) {
279    Button('Previous')
280      .onClick(() => {
281        this.scroller.scrollPage({
282          next: false
283        })
284      })
285
286    Button('Next')
287      .onClick(() => {
288        this.scroller.scrollPage({
289          next: true
290        })
291      })
292  }
293}
294```
295
296
297## Adding an External Scrollbar
298
299To add an external scrollbar to a [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md) component, you can use the [ScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-scrollbar.md) component. By binding both the **Grid** and **ScrollBar** components to the same [Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller) object, you can ensure they stay synchronized.
300
3011. Create a [Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller) object named **gridScroller**.
302
303   ```ts
304   private gridScroller: Scroller = new Scroller();
305   ```
306
3072. Bind the **gridScroller** object to the **Grid** component using the [scroller](../reference/apis-arkui/arkui-ts/ts-container-grid.md#apis) parameter.
308
309   ```ts
310   // Use gridScroller to initialize the scroller parameter to bind it with the Grid component.
311   Grid({ scroller: this.gridScroller }) {
312   // ...
313   }
314   ```
315
3163. Bind the **gridScroller** object to the **ScrollBar** component using the [scroller](../reference/apis-arkui/arkui-ts/ts-basic-components-scrollbar.md#scrollbaroptions) parameter.
317
318   ```ts
319   // Use gridScroller to initialize the scroller parameter to bind it with the ScrollBar component.
320   ScrollBar({ scroller: this.gridScroller })
321   ```
322
323  **Figure 11** External scrollbar of the Grid component
324
325![ScrollBar](figures/grid_scrollbar.gif)
326
327>**NOTE**
328>- The [ScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-scrollbar.md) component can also be used with other scrollable components such as [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md), [List](../reference/apis-arkui/arkui-ts/ts-container-list.md), [Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md), and [WaterFlow](../reference/apis-arkui/arkui-ts/ts-container-waterflow.md).
329>- On devices with circular screens, you can use the [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md) component with the [ArcScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md) component to add an arc scrollbar to your grid layout. For details, see [Adding an External Scrollbar: ArcScrollBar](./arkts-layout-development-create-arclist.md#adding-an-external-scrollbar-arcscrollbar).
330
331## Performance Optimization
332
333Just as [LazyForEach](../quick-start/arkts-rendering-control-lazyforeach.md) is recommended for [handling a long list](arkts-layout-development-create-list.md#handling-a-long-list), it is also recommended for a scrolling grid layout when a large number of grid items is involved.
334
335For details about the implementation, see the example in [LazyForEach: Lazy Data Loading](../quick-start/arkts-rendering-control-lazyforeach.md).
336
337When the grid is rendered in lazy loading mode, to improve the grid scrolling experience and minimize white blocks during grid scrolling, you can use the **cachedCount** parameter of the **Grid** component. This parameter sets the number of grid items preloaded outside of the screen and is valid only in **LazyForEach**.
338
339  Specifically, the number of the grid items to cache before and after the currently displayed one equals the value of **cachedCount** multiplied by the number of columns. Grid items that exceed the display and cache range are released.
340
341```ts
342Grid() {
343  LazyForEach(this.dataSource, () => {
344    GridItem() {
345    }
346  })
347}
348.cachedCount(3)
349```
350
351>**NOTE**
352>
353>A greater **cachedCount** value may result in higher CPU and memory overhead of the UI. Adjust the value by taking into account both the comprehensive performance and user experience.
354