• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Creating an Arc List (ArcList) (Recommended for Circular Screens)
2
3The **ArcList** component is a specialized list designed for devices with circular screens, capable of efficiently displaying information in a structured, scrollable format. For details, see [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md).
4
5You can linearly arrange child components, [ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md), vertically within the [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md) component. This allows each item in the **ArcList** to have its own view. To build a complex **ArcList**, you can use [ForEach](../quick-start/arkts-rendering-control-foreach.md) to iterate over a set of list items or combine any number of individual views with the **ForEach** structure. The [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md) component supports various [rendering control](../quick-start/arkts-rendering-control-overview.md) methods, including conditional rendering, loop rendering, and lazy loading, to generate child components.
6
7## Creating an ArcList Component
8
9To create an [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md) component, use the following:
10
11```ts
12ArcList() {
13  ArcListItem() {
14    // ...
15  }
16  ArcListItem() {
17    // ...
18  }
19  // ...
20}
21```
22
23>**NOTE**
24>
25>The child components of the **ArcList** must be **ArcListItem**. **ArcListItem** must be used in conjunction with **ArcList**.
26
27## Displaying Data in the ArcList Component
28
29The **ArcList** component displays a collection of items vertically and provides scrolling functionality when items exceed the screen boundaries. This makes it ideal for displaying large datasets. In the simplest form of an **ArcList**, the list items, **ArcListItem**, are statically created within the **ArcList**.
30
31```ts
32// xxx.ets
33import { ArcList, ArcListItem, ArcListAttribute, ArcListItemAttribute, LengthMetrics } from "@kit.ArkUI";
34
35@Entry
36@Component
37struct ArcListExample {
38  build() {
39    ArcList({ initialIndex: 2 }) {
40      ArcListItem() {
41        Row() {
42          Image($r("app.media.wlan")).width("99px").height("99px")
43            .borderRadius("50px").margin({ left: 7 })
44          Column() {
45            Text("WLAN").fontSize("38px").fontColor("#FFFFFFFF")
46            Text("On").fontSize("20px").fontColor("#FFFFFFFF")
47          }.width("190px")
48
49          Image($r("app.media.ic_settings_arrow")).width("92px").height("92px")
50            .borderRadius("50px")
51        }
52      }
53      .borderRadius("65px")
54      .width("414px")
55      .height("129px")
56      .backgroundColor("#26FFFFFF")
57
58      ArcListItem() {
59        Row() {
60          Image($r("app.media.blueTooth")).width("99px").height("99px")
61            .borderRadius("50px").margin({ left: 7 })
62          Column() {
63            Text("Bluetooth").fontSize("38px").fontColor("#FFFFFFFF")
64            Text("On").fontSize("20px").fontColor("#FFFFFFFF")
65          }.width("190px")
66
67          Image($r("app.media.ic_settings_arrow")).width("92px").height("92px")
68            .borderRadius("50px")
69        }
70      }
71      .borderRadius("65px")
72      .width("414px")
73      .height("129px")
74      .backgroundColor("#26FFFFFF")
75
76      ArcListItem() {
77        Row() {
78          Image($r("app.media.mobileData")).width("99px").height("99px")
79            .borderRadius("50px").margin({ left: 7 })
80          Column() {
81            Text("Mobile network").fontSize("38px").fontColor("#FFFFFFFF")
82          }.width("190px")
83
84          Image($r("app.media.ic_settings_arrow")).width("92px").height("92px")
85            .borderRadius("50px")
86        }
87      }
88      .borderRadius("65px")
89      .width("414px")
90      .height("129px")
91      .backgroundColor("#26FFFFFF")
92
93      ArcListItem() {
94        Row() {
95          Image($r("app.media.ic_settings_more_connections")).width("99px").height("99px")
96            .borderRadius("50px").margin({ left: 7 })
97          Column() {
98            Text("More connections").fontSize("38px").fontColor("#FFFFFFFF")
99          }.width("190px")
100
101          Image($r("app.media.ic_settings_arrow")).width("92px").height("92px")
102            .borderRadius("50px")
103        }
104      }
105      .borderRadius("65px")
106      .width("414px")
107      .height("129px")
108      .backgroundColor("#26FFFFFF")
109
110      ArcListItem() {
111        Row() {
112          Image($r("app.media.displayAndBrightness")).width("99px").height("99px")
113            .borderRadius("50px").margin({ left: 7 })
114          Column() {
115            Text("Display & brightness").fontSize("38px").fontColor("#FFFFFFFF")
116          }.width("190px")
117
118          Image($r("app.media.ic_settings_arrow")).width("92px").height("92px")
119            .borderRadius("50px")
120        }
121      }
122      .borderRadius("65px")
123      .width("414px")
124      .height("129px")
125      .backgroundColor("#26FFFFFF")
126    }
127    .width("466px")
128    .height("466px")
129    .space(LengthMetrics.px(10))
130    .borderRadius("233px")
131    .backgroundColor(Color.Black)
132  }
133}
134```
135
136  **Figure 1** Displaying data in the ArcList component
137
138![arcList_item](figures/arcList_item.png)
139
140## Iterating ArcList Content
141
142Typically, applications dynamically create lists from data collections. Using [loop rendering](../quick-start/arkts-rendering-control-foreach.md), you can iterate over the data source to create corresponding components during each iteration, thereby reducing code complexity.
143
144ArkTS provides loop rendering capabilities through [ForEach](../quick-start/arkts-rendering-control-foreach.md). For example, in a simple contacts list, contact names and profile picture data are stored in a **contacts** array using a **Contact** class structure. By using [ForEach](../quick-start/arkts-rendering-control-foreach.md) with nested [ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md), you can replace multiple similar, flat-laid-out **ArcListItem** components, reducing redundant code and making your code more concise and efficient.
145
146```ts
147// xxx.ets
148import { ArcList, ArcListAttribute, ArcListItemAttribute, ArcListItem, LengthMetrics } from '@kit.ArkUI';
149import { util } from '@kit.ArkTS';
150
151class Contact {
152  key: string = util.generateRandomUUID(true);
153  name: string;
154  icon: Resource;
155
156  constructor(name: string, icon: Resource) {
157    this.name = name;
158    this.icon = icon;
159  }
160}
161
162@Entry
163@Component
164struct SimpleContacts {
165  private contacts: Array<object> = [
166    new Contact('Alice', $r("app.media.ic_contact")),
167    new Contact('Bob', $r("app.media.ic_contact")),
168    new Contact('Charlie', $r("app.media.ic_contact")),
169    new Contact('Diana', $r("app.media.ic_contact")),
170    new Contact('Eve', $r("app.media.ic_contact"))
171  ]
172
173  build() {
174    ArcList({ initialIndex: 2 }) {
175      ForEach(this.contacts, (item: Contact) => {
176        ArcListItem() {
177          Row() {
178            Image(item.icon)
179              .width(40)
180              .height(40)
181              .margin(10)
182              .backgroundColor("#FF9CC998")
183              .borderRadius(20)
184            Text(item.name).fontSize("38px").fontColor("#FFFFFFFF")
185          }
186          .width('100%')
187          .justifyContent(FlexAlign.Start)
188        }
189        .borderRadius("65px")
190        .width("410px")
191        .height('130px')
192        .backgroundColor("#26FFFFFF")
193      }, (item: Contact) => JSON.stringify(item))
194    }
195    .space(LengthMetrics.px(10))
196    .width('466px')
197    .height('466px')
198    .borderRadius('233px')
199    .backgroundColor(Color.Black)
200  }
201}
202```
203
204  **Figure 2** Iterating ArcList content
205
206![arcList_foreach](figures/arcList_foreach.png)
207
208## Customizing the ArcList Style
209
210### Setting a Custom Header
211
212You can add a custom header to an ArcList using the [header](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions) parameter.
213
2141. Construct the custom header component, **customHeader**.
215
216   ```ts
217   @Builder
218   function customHeader() {
219     Column() {
220       Text("Settings")
221         .fontColor("#FFFFFFFF")
222         .fontSize('19fp')
223     }
224   }
225   ```
226
2272. Wrap the custom header component. This step is required because the [header](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions) parameter expects a [ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md) type.
228
229   ```ts
230   context: UIContext = this.getUIContext();
231   arcListHeader: ComponentContent<Object> = new ComponentContent(this.context, wrapBuilder(customHeader));
232   ```
233
2343. Set the **arcListHeader **to the **ArcList** component using the **header** parameter.
235
236   ```ts
237   ArcList({header: this.arcListHeader}) {
238     ArcListItem() {
239       // ...
240     }
241     ArcListItem() {
242       // ...
243     }
244     // ...
245   }
246   ```
247
248  **Figure 3** Setting a custom header
249
250![arcList_header](figures/arcList_header.png)
251
252### Setting the List Item Spacing
253
254When initializing the **ArcList** component, you can use the [space](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#space) attribute to add spacing between list items. For example, to add a vertical spacing of 30 px between list items:
255
256```ts
257ArcList() {
258  // ...
259}
260.space(LengthMetrics.px(30))
261```
262
263  **Figure 4** Setting the list item spacing
264
265![arcList_space](figures/arcList_space.png)
266
267### Disabling Auto-Scaling for List Items
268
269By default, items in an **ArcList** component automatically scale when they are near the top or bottom edges. However, in some cases, you might not want this scaling effect. To disable it, set the [autoScale](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#autoscale) attribute of [ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md) to **false**. For example, as shown in Figure 5, the **Network** and **Display** list items do not scale regardless of their position after thire **autoScale** attribute is disabled.
270
271```ts
272ArcListItem() {
273  // ...
274}
275.autoScale(false)
276```
277
278  **Figure 5** Disabling auto-scaling for list items
279
280![arcListItem_autoScale](figures/arcListItem_autoScale.png)
281
282### Adding a Built-in Scrollbar
283
284When the height of the list items exceeds the screen height, the **ArcList** component can scroll vertically. To help users quickly navigate, a scrollbar can be provided to allow rapid scrolling through the list, as shown in Figure 6.
285
286When using the [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md) component, you can control the display of the scrollbar using the [scrollBar](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbar) attribute. The value of **scrollBar** is of type [BarState](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#barstate). When set to **BarState.Auto**, the scrollbar is displayed as needed. In this mode, the scrollbar appears when the user touches the scrollbar area, allowing for up and down dragging to quickly scroll through the content. The scrollbar also thickens during dragging for better visibility. If the user takes no action, the scrollbar automatically disappears after 2 seconds. You can customize the scrollbar style, using the [scrollBarWidth](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbarwidth) attribute to set its width in the pressed state and the [scrollBarColor](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbarcolor) attribute to set its color.
287
288```ts
289ArcList() {
290  // ...
291}
292.scrollBar(BarState.Auto)
293.scrollBarWidth(LengthMetrics.px(10))
294.scrollBarColor(ColorMetrics.resourceColor(Color.White))
295```
296
297  **Figure 6** Built-in scrollbar of the ArcList component
298
299![arcList_scrollBar](figures/arcList_scrollBar.gif)
300
301### Adding an External Scrollbar: ArcScrollBar
302
303To add an external scrollbar to an [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md), you can use the [ArcScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md) component. By binding both the **ArcList** and **ArcScrollBar** components to the same [Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller) object, you can ensure they stay synchronized.
304
3051. Create a **Scroller** object named **arcListScroller**.
306
307   ```ts
308   private arcListScroller: Scroller = new Scroller();
309   ```
310
3112. Bind the **arcListScroller** object to the **ArcList** component using the [scroller](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions) parameter.
312
313   ```ts
314   // Use arcListScroller to initialize the scroller parameter to bind it with the ArcList component.
315   ArcList({ scroller: this.arcListScroller }) {
316   // ...
317   }
318   ```
319
3203. Bind the **arcListScroller** object to the **ArcScrollBar** component using the [scroller](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md#arcscrollbaroptions) parameter.
321
322   ```ts
323   // Use arcListScroller to initialize the scroller parameter to bind it with the ArcScrollBar component.
324   ArcScrollBar({ scroller: this.arcListScroller })
325   ```
326
327  **Figure 7** External scrollbar of the ArcList component
328
329![arcScrollBar](figures/arcScrollBar.gif)
330
331>**NOTE**
332>
333>The [ArcScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md) component can also be used with other scrollable components such as [List](../reference/apis-arkui/arkui-ts/ts-container-list.md), [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md), and [Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md).
334
335## Interacting with ArcAlphabetIndexer
336
337Applications often need to monitor changes in the scroll position of a list and respond accordingly, or quickly navigate to specific sections by adjusting the scroll position. For example, in a contacts list, as the list scrolls through different sections (for example, from "A" to "B"), the external index bar should update to reflect the current letter. When a user selects an index item (for example, "C"), the list should jump to the corresponding section. To achieve this functionality, you can use the [ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md) component.
338
339As shown in Figure 8, when the list scrolls from contacts starting with "A" to those starting with "B," the external index bar should also update from the selected "A" state to the selected "B" state. This can be achieved by listening for the [onScrollIndex](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#onscrollindex) event of the **ArcList** component. When an index item "C" is clicked, the list should jump to the contacts starting with "C." This can be achieved by listening for the [onSelect](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md#onselect) event of the [ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md) component.
340
341When the list scrolls, the **selectedIndex** value of the letter to highlight in the alphabet index bar is recalculated based on the **firstIndex** value of the item to which the list has scrolled. Since the **ArcAlphabetIndexer** component uses the [selected](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md#selected) attribute to set the selected item index, changes to **selectedIndex** will trigger the **ArcAlphabetIndexer** component to re-render and display the selected letter state.
342
343When an index item is selected, the selected item index (**index**) is used to recalculate the corresponding position in the list. The list is then scrolled to that position using the [scrollToIndex](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scrolltoindex) API of the bound scroll controller (**arcListScroller**). The **ArcList** component can be bound to a [Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller) (scroll controller) object using the [scroller](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions) parameter.
344
345```ts
346const alphabets = ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
347  'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
348@Entry
349@Component
350struct ContactsArcList {
351  // Index of the selected item in the index bar
352  @State selectedIndex: number = 0;
353  // Scroll controller bound to the list
354  private arcListScroller: Scroller = new Scroller();
355
356  build() {
357    Stack({ alignContent: Alignment.End }) {
358      ArcList({ scroller: this.arcListScroller }) {
359        // ...
360      }
361      .onScrollIndex((firstIndex: number) => {
362        // Recalculate the corresponding index bar position based on the index of the item to which the list has scrolled.
363        this.selectedIndex = firstIndex + 1;
364      })
365
366      // ArcAlphabetIndexer component
367      ArcAlphabetIndexer({ arrayValue: alphabets })
368        .selected(this.selectedIndex)
369        .onSelect((index: number) => {
370          // Scroll the list to the corresponding position when an index item is selected.
371          this.selectedIndex = index
372          this.scrollerForList.scrollToIndex(this.selectedIndex - 1)
373        })
374    }
375  }
376}
377```
378
379  **Figure 8** Interaction between the ArcList and ArcAlphabetIndexer
380
381![arcAlphabetIndexer](figures/arcAlphabetIndexer.gif)
382
383## Responding to Swipe on List Items
384
385To enable swipe gestures on list items in the **ArcList** component, you can use the [swipeAction](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#swipeaction) attribute of **ArcListItem**. This attribute requires a [SwipeActionOptions](../reference/apis-arkui/arkui-ts/ts-container-listitem.md#swipeactionoptions9) object with **start** and **end** parameters. Here, **start** defines the swipe action item displayed on the start edge of the list item when the item is swiped right, while **end** defines the swipe action item displayed on the end edge of the list item when the item is swiped left.
386
387For example, in a contacts list, you can use the **end** parameter to show a delete button when an item is swiped left. When the delete button is clicked, you can remove the corresponding item from the data source.
388
3891. Build the component that appears from the end edge when the list item is swiped left.
390   ```ts
391   @Builder
392   itemEnd(item: Contact) {
393     // Build the component that appears from the end edge when the list item is swiped left.
394     Button({ type: ButtonType.Circle }) {
395       Image($r('app.media.ic_public_delete_filled'))
396         .width(20)
397         .height(20)
398     }
399     .backgroundColor(Color.Black)
400     .onClick(() => {
401       animateTo({
402         duration: 1000,
403         curve: Curve.Smooth,
404         iterations: 1,
405         playMode: PlayMode.Normal,
406       }, () => {
407         // this.contacts is the data source. The indexOf API obtains the index of the item to be deleted.
408         let index = this.contacts.indexOf(item)
409         // Remove the specified data item from the data source.
410         this.contacts.splice(index, 1)
411       })
412     })
413   }
414   ```
415
4162. Bind the [swipeAction](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#swipeaction) attribute to the **ArcListItem** that can be swiped left.
417
418   ```ts
419   // When constructing an ArcList component, use ForEach to render list items based on the data source this.contacts.
420   ArcListItem() {
421     // ...
422   }
423   .swipeAction({
424     end: {
425       // item is the data corresponding to this list item in the data source this.contacts.
426       builder: () => { this.itemEnd(item) }
427     }
428   }) // Set the swipe action.
429   ```
430
431  **Figure 9** Swipe-to-delete feature
432
433![arcListItem_swipeAction](figures/arcListItem_swipeAction.gif)
434
435## Handling Long Lists
436
437While [ForEach](../quick-start/arkts-rendering-control-foreach.md) is suitable for short lists, using it for long lists with a large number of items can significantly slow down page loading, as it loads all items at once. Therefore, for better list performance, use [LazyForEach](../quick-start/arkts-rendering-control-lazyforeach.md) instead to implement on-demand iterative data loading. For details about the implementation, see the example in [LazyForEach: Lazy Data Loading](../quick-start/arkts-rendering-control-lazyforeach.md).
438
439When the list is rendered in lazy loading mode, to improve the list scrolling experience and minimize white blocks during list scrolling, you can use the [cachedCount](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#cachedcount) attribute of the [ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md) component. This attribute sets the number of list items preloaded outside of the screen and is valid only in [LazyForEach](../quick-start/arkts-rendering-control-lazyforeach.md).
440
441```ts
442ArcList() {
443  // ...
444}.cachedCount(3)
445```
446
447>**NOTE**
448>
449>- 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.
450>
451>- When a list uses data lazy loading, all list items except the list items in the display area and the cached list items are destroyed.
452
453## Responding to Digital Crown Rotations
454
455On wearable devices, the **ArcList** component can respond to digital crown rotations when it is in focus. Users can scroll through the list items by rotating the crown. To make the **ArcList** the default focus on the page and enable it to respond to crown rotations, you can use the following [focus control](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md) attributes:
456
457```ts
458ArcList() {
459  // ...
460}
461// Enable focus for the ArcList component.
462.focusable(true)
463// Allow the ArcList component to gain focus on touch.
464.focusOnTouch(true)
465// Set the ArcList component as the default focus on the page.
466.defaultFocus(true)
467```
468
469You can also adjust the sensitivity of the digital crown response using the [digitalCrownSensitivity](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#digitalcrownsensitivity) attribute. This allows you to fine-tune the responsiveness based on the amount of data in the list. For lists with more items, you might want to increase the sensitivity, while for lists with fewer items, you can decrease it.
470
471```ts
472ArcList() {
473  // ...
474}
475.digitalCrownSensitivity(CrownSensitivity.MEDIUM)
476```
477