1# 弧形列表 (ArcList)(圆形屏幕推荐使用) 2 3弧形列表是一种专为圆形屏幕设备设计的特殊列表,它能够以结构化、可滚动的形式高效展示信息。具体用法可参考[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)。 4 5使用弧形列表可以通过在[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)组件中按垂直方向线性排列子组件[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md),可以为弧形列表中的每一项提供独立视图。此外,可以使用[循环渲染](../ui/state-management/arkts-rendering-control-foreach.md)来迭代一组列表项,或结合任意数量的单个视图与[ForEach](../ui/state-management/arkts-rendering-control-foreach.md)结构,构建复杂的弧形列表。[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)组件支持多种[渲染控制](../ui/state-management/arkts-rendering-control-overview.md)方式,包括条件渲染、循环渲染和懒加载,以生成子组件。 6 7## 创建弧形列表 8 9[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)可通过调用以下接口来创建。 10 11```ts 12ArcList() { 13 ArcListItem() { 14 // ... 15 } 16 ArcListItem() { 17 // ... 18 } 19 // ... 20} 21``` 22 23>**说明:** 24> 25>[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)的子组件必须是[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md),[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)必须配合[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)来使用。 26 27## 在弧形列表中显示数据 28 29弧形列表视图垂直展示项目集合,当列表项超出屏幕范围时,提供滚动功能,这使得它非常适合展示大型数据集合。在最简单的弧形列表形式中,[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)静态创建其列表项[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)的内容。 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("已开启").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("蓝牙").fontSize("38px").fontColor("#FFFFFFFF") 64 Text("已开启").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("移动网络").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("更多连接").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("显示和亮度").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 **图1** 显示弧形列表数据 137 138 139 140## 迭代弧形列表内容 141 142通常,应用会通过数据集合动态创建列表。采用[循环渲染](../ui/state-management/arkts-rendering-control-foreach.md)的方式,可以从数据源中迭代获取数据,在每次迭代过程中创建相应的组件,从而降低代码的复杂度。 143 144ArkTS通过[ForEach](../ui/state-management/arkts-rendering-control-foreach.md)提供了组件的循环渲染能力。以简单的联系人列表为例,将联系人名称和头像数据以Contact类结构存储到contacts数组中,使用[ForEach](../ui/state-management/arkts-rendering-control-foreach.md)中嵌套的[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)来代替多个平铺的、内容相似的[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md),从而减少重复代码,使代码更加简洁高效。 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('小红', $r("app.media.ic_contact")), 167 new Contact('小兰', $r("app.media.ic_contact")), 168 new Contact('小王', $r("app.media.ic_contact")), 169 new Contact('小李', $r("app.media.ic_contact")), 170 new Contact('小明', $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 **图2** 迭代弧形列表内容 205 206 207 208## 自定义弧形列表样式 209 210### 自定义弧形列表标题 211 212可以通过[header](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions)参数为弧形列表添加自定义标题。 213 2141. 首先,需要构造自定义标题组件customHeader。 215 216 ```ts 217 @Builder 218 function customHeader() { 219 Column() { 220 Text("设置") 221 .fontColor("#FFFFFFFF") 222 .fontSize('19fp') 223 } 224 } 225 ``` 226 2272. 由于[header](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions)参数的类型是[ComponentContent](../reference/apis-arkui/js-apis-arkui-ComponentContent.md),所以需要对自定义标题组件进行封装。 228 229 ```ts 230 context: UIContext = this.getUIContext(); 231 arcListHeader: ComponentContent<Object> = new ComponentContent(this.context, wrapBuilder(customHeader)); 232 ``` 233 2343. 最后,通过[header](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions)参数将arcListHeader设置到弧形列表中。 235 236 ```ts 237 ArcList({header: this.arcListHeader}) { 238 ArcListItem() { 239 // ... 240 } 241 ArcListItem() { 242 // ... 243 } 244 // ... 245 } 246 ``` 247 248 **图3** 自定义弧形列表标题 249 250 251 252### 设置弧形列表项间距 253 254在初始化列表时,若需在列表项之间添加间距,可以通过[space](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#space)属性实现。例如,为在每个列表项的垂直方向上增加30px的间距。 255 256```ts 257ArcList() { 258 // ... 259} 260.space(LengthMetrics.px(30)) 261``` 262 263 **图4** 设置弧形列表项间距 264 265 266 267### 列表项关闭自动缩放 268 269在弧形列表中,列表项默认具有在接近上下两端时自动缩放的效果。然而,在某些情况下,可能不希望有这种缩放效果。此时,可以通过设置[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)的[autoScale](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#autoscale)属性为false来禁用该效果。例如,如图5所示,“网络”和“显示”两个列表项,在关闭了自动缩放属性后,无论它们所处的位置如何,都不会出现缩放效果。 270 271```ts 272ArcListItem() { 273 // ... 274} 275.autoScale(false) 276``` 277 278 **图5** 列表项关闭自动缩放 279 280 281 282### 添加内置滚动条 283 284当列表项的高度超过屏幕高度时,弧形列表能够沿垂直方向滚动。若用户需要快速定位,可拖动滚动条以迅速滑动列表,如图6所示。 285 286在使用[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)组件时,可以通过[scrollBar](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbar)属性来控制弧形列表滚动条的显示。scrollBar的取值类型为[BarState](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#barstate),当设置为BarState.Auto时,表示滚动条将按需显示。在这种模式下,当用户触摸到滚动条区域时,滚动条会显示出来,支持上下拖拽以快速浏览内容,且在拖拽过程中滚动条会变粗。若用户不进行任何操作,滚动条将在2秒后自动消失。此外,还可以通过[scrollBarWidth](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbarwidth)属性来设置滚动条在按压状态下的宽度,以及通过[scrollBarColor](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#scrollbarcolor)属性来设置滚动条的颜色。 287 288```ts 289ArcList() { 290 // ... 291} 292.scrollBar(BarState.Auto) 293.scrollBarWidth(LengthMetrics.px(10)) 294.scrollBarColor(ColorMetrics.resourceColor(Color.White)) 295``` 296 297 **图6** 弧形列表的内置滚动条 298 299 300 301## 添加外置滚动条ArcScrollBar 302 303弧形列表[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)可与[ArcScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md)组件配合使用,为弧形列表添加外置滚动条。两者通过绑定同一个[Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller)滚动控制器对象实现联动。 304 3051. 首先,需要创建一个[Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller)类型的对象arcListScroller。 306 307 ```ts 308 private arcListScroller: Scroller = new Scroller(); 309 ``` 310 3112. 然后,弧形列表通过[scroller](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions)参数绑定滚动控制器。 312 313 ```ts 314 // 将arcListScroller用于初始化ArcList组件的scroller参数,完成arcListScroller与弧形列表的绑定。 315 ArcList({ scroller: this.arcListScroller }) { 316 // ... 317 } 318 ``` 319 3203. 最后,弧形滚动条通过[scroller](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md#arcscrollbaroptions)参数绑定滚动控制器。 321 322 ```ts 323 // 将arcListScroller用于初始化ArcScrollBar组件的scroller参数,完成arcListScroller与滚动条的绑定。 324 ArcScrollBar({ scroller: this.arcListScroller }) 325 ``` 326 327 **图7** 弧形列表的外置滚动条 328 329 330 331>**说明:** 332> 333>弧形滚动条组件[ArcScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-arcscrollbar.md),还可配合其他可滚动组件使用,如[List](../reference/apis-arkui/arkui-ts/ts-container-list.md)、[Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md)、[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md)、[WaterFlow](../reference/apis-arkui/arkui-ts/ts-container-waterflow.md)。 334 335## 与弧形索引条ArcAlphabetIndexer联动 336 337许多应用需要监测列表的滚动位置变动并作出响应,或通过调整滚动位置实现列表的快速定位。例如,在联系人列表滚动时,当列表滚动至不同首字母开头的联系人,外部索引条应更新至相应的字母位置。当用户选择外部索引条上的索引项时,列表应跳转至对应位置。为此,需使用弧形索引条组件[ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md)。 338 339如图8所示,当列表从联系人A滚动到联系人B时,外侧索引条也需要同步从选中A状态变成选中B状态,此场景可以通过监听[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)组件的[onScrollIndex](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#onscrollindex)事件来实现;当点击索引项C时,列表也需要跳转到联系人C,此场景可以通过监听[ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md)的[onSelect](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md#onselect)事件来实现。 340 341在列表滚动时,根据列表此时所在的索引值位置firstIndex,重新计算字母索引条对应字母的位置selectedIndex。由于[ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md)组件通过[selected](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md#selected)属性设置了选中项索引值,当selectedIndex变化时会触发[ArcAlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-arc-alphabet-indexer.md)组件重新渲染,从而显示为选中对应字母的状态。 342 343在选中索引项时,根据此时选中项的索引值index,重新计算列表联系人对应的位置,然后通过列表绑定的滚动控制器arcListScroller的[scrollToIndex](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scrolltoindex)方法控制列表跳转到对应的联系人位置。弧形列表[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)可通过[scroller](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#arklistoptions)参数绑定[Scroller](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#scroller)(滚动控制器)。 344 345```ts 346const alphabets = ['#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', '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 // 索引条选中项索引 352 @State selectedIndex: number = 0; 353 // 列表绑定的滚动控制器 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 // 根据列表滚动到的索引值,重新计算对应索引条的位置this.selectedIndex 363 this.selectedIndex = firstIndex + 1; 364 }) 365 366 // 弧形索引条组件 367 ArcAlphabetIndexer({ arrayValue: alphabets }) 368 .selected(this.selectedIndex) 369 .onSelect((index: number) => { 370 // 选中索引项后,列表跳转到相应位置 371 this.selectedIndex = index 372 this.scrollerForList.scrollToIndex(this.selectedIndex - 1) 373 }) 374 } 375 } 376} 377``` 378 379 **图8** 弧形列表与弧形索引条联动 380 381 382 383## 响应列表项侧滑 384 385[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)的[swipeAction](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#swipeaction)属性可用于实现列表项的左右滑动功能。[swipeAction](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#swipeaction)属性方法初始化时存在必填[SwipeActionOptions](../reference/apis-arkui/arkui-ts/ts-container-listitem.md#swipeactionoptions9对象说明)参数start和end。其中,start表示设置列表项右滑时起始端滑出的组件,end表示设置列表项左滑时尾端滑出的组件。 386 387在联系人列表中,end参数表示设置[ArcListItem](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md)左滑时尾端划出自定义组件,即删除按钮。在初始化end方法时,将滑动列表项的索引传入删除按钮组件,当用户点击删除按钮时,可以根据数据索引来删除列表项对应的数据,从而实现侧滑删除功能。 388 3891. 首先,实现尾端滑出组件的构建。 390 ```ts 391 @Builder 392 itemEnd(item: Contact) { 393 // 构建尾端滑出组件 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 this.getUIContext()?.animateTo({ 402 duration: 1000, 403 curve: Curve.Smooth, 404 iterations: 1, 405 playMode: PlayMode.Normal, 406 }, () => { 407 // this.contacts为列表数据源,可根据实际场景构造,indexOf方法可获取将被删除数据在数据源中的索引 408 let index = this.contacts.indexOf(item) 409 // 从数据源删除指定数据项 410 this.contacts.splice(index, 1) 411 }) 412 }) 413 } 414 ``` 415 4162. 然后,绑定[swipeAction](../reference/apis-arkui/arkui-ts/ts-container-arclistitem.md#swipeaction)属性到可左滑的ArcListItem上。 417 418 ```ts 419 // 构建ArcList时,通过ForEach基于数据源this.contacts循环渲染ArcListItem 420 ArcListItem() { 421 // ... 422 } 423 .swipeAction({ 424 end: { 425 // item为该列表项在数据源this.contacts中对应的数据 426 builder: () => { this.itemEnd(item) } 427 } 428 }) // 设置侧滑属性 429 ``` 430 431 **图9** 侧滑删除列表项 432 433 434 435## 处理长列表 436 437[循环渲染](../ui/state-management/arkts-rendering-control-foreach.md)适用于短列表,当构建具有大量列表项的长列表时,如果直接采用循环渲染方式,会一次性加载所有的列表元素,会导致页面启动时间过长,影响用户体验。因此,推荐使用[数据懒加载](../ui/state-management/arkts-rendering-control-lazyforeach.md)(LazyForEach)方式实现按需迭代加载数据,从而提升列表性能。关于长列表按需加载优化的具体实现可参考[数据懒加载](../ui/state-management/arkts-rendering-control-lazyforeach.md)章节中的示例。 438 439当使用懒加载方式渲染列表时,为了减少列表滑动时出现白块,[ArcList](../reference/apis-arkui/arkui-ts/ts-container-arclist.md)组件提供了[cachedCount](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#cachedcount)属性,该属性用于设置列表项缓存数,只在懒加载[LazyForEach](../ui/state-management/arkts-rendering-control-lazyforeach.md)中生效。 440 441```ts 442ArcList() { 443 // ... 444}.cachedCount(3) 445``` 446 447>**说明:** 448> 449>- cachedCount的增加会增大UI的CPU、内存开销。使用时需要根据实际情况,综合性能和用户体验进行调整。 450> 451>- 列表使用数据懒加载时,除了显示区域的列表项和前后缓存的列表项,其他列表项会被销毁。 452 453## 响应旋转表冠 454 455手表设备上弧形列表在获焦的情况下可对旋转表冠做出响应,用户可通过旋转表冠的操作滑动列表,浏览列表项数据。弧形列表可通过下列[焦点控制](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md)相关属性成为所在页面的默认焦点。 456 457```ts 458ArcList() { 459 // ... 460} 461// 设置弧形列表支持获焦 462.focusable(true) 463// 设置弧形列表支持点击获焦 464.focusOnTouch(true) 465// 设置弧形列表为所在页面上的默认焦点 466.defaultFocus(true) 467``` 468 469还可以通过[digitalCrownSensitivity](../reference/apis-arkui/arkui-ts/ts-container-arclist.md#digitalcrownsensitivity)属性设置表冠响应事件的灵敏度,以应对不同量级的列表项数据。列表项数据较多时可以设置更高的响应事件灵敏度,数据较少时可以设置较低的响应事件灵敏度。 470 471```ts 472ArcList() { 473 // ... 474} 475.digitalCrownSensitivity(CrownSensitivity.MEDIUM) 476```