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 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 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 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 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 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 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 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 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 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