1# TreeView 2 3 4The **TreeView** component represents a tree view used to display a hierarchical list of items. Each item can contain subitems, which may be expanded or collapsed. 5 6 7This component is applicable in productivity applications, such as side navigation bars in notepad, email, and Gallery applications. 8 9 10> **NOTE** 11> 12> This component is supported since API version 10. Updates will be marked with a superscript to indicate their earliest API version. 13> 14> This component is not supported on wearables. 15 16 17## Modules to Import 18 19``` 20import { TreeView } from "@kit.ArkUI"; 21``` 22 23 24## Child Components 25 26Not supported 27 28## Attributes 29The [universal attributes](ts-component-general-attributes.md) are not supported. 30 31## TreeView 32 33TreeView({ treeController: TreeController }) 34 35**Decorator**: @Component 36 37**Atomic service API**: This API can be used in atomic services since API version 11. 38 39**System capability**: SystemCapability.ArkUI.ArkUI.Full 40 41 42| Name| Type| Mandatory| Description| 43| -------- | -------- | -------- | -------- | 44| treeController | [TreeController](#treecontroller) | Yes| Node information of the tree view.| 45 46 47## TreeController 48 49Implements a **TreeController** object, which can be bound to a tree view component to control the node information of the component. One **TreeController** object can be bound to only one tree view component. 50 51**Atomic service API**: This API can be used in atomic services since API version 11. 52 53**System capability**: SystemCapability.ArkUI.ArkUI.Full 54 55 56### addNode 57 58 59addNode(nodeParam?: NodeParam): TreeController 60 61Adds a child node to the selected node. 62 63**Atomic service API**: This API can be used in atomic services since API version 11. 64 65**System capability**: SystemCapability.ArkUI.ArkUI.Full 66 67 68| Name| Type| Mandatory| Description| 69| -------- | -------- | -------- | -------- | 70| nodeParam | [NodeParam](#nodeparam) | No| Node information.| 71 72**Return value** 73 74| Type | Description | 75| --------------------------------- | -------------------- | 76| [TreeController](#treecontroller) | Controller of the **TreeView** component.| 77 78### removeNode 79 80removeNode(): void 81 82Removes the selected node. 83 84**Atomic service API**: This API can be used in atomic services since API version 11. 85 86**System capability**: SystemCapability.ArkUI.ArkUI.Full 87 88 89### modifyNode 90 91 92modifyNode(): void 93 94Modifies the selected node. 95 96**Atomic service API**: This API can be used in atomic services since API version 11. 97 98**System capability**: SystemCapability.ArkUI.ArkUI.Full 99 100 101### buildDone 102 103buildDone(): void 104 105Builds a tree view. After a node is added, this API must be called to save the tree information. 106 107**Atomic service API**: This API can be used in atomic services since API version 11. 108 109**System capability**: SystemCapability.ArkUI.ArkUI.Full 110 111 112### refreshNode 113 114refreshNode(parentId: number, parentSubTitle: ResourceStr, currentSubtitle: ResourceStr): void 115 116Refreshes the tree view. You can call this API to update the information about the current node. 117 118**Atomic service API**: This API can be used in atomic services since API version 11. 119 120**System capability**: SystemCapability.ArkUI.ArkUI.Full 121 122| Name| Type| Mandatory| Description| 123| -------- | -------- | -------- | -------- | 124| parentId | number | Yes| ID of the parent node.| 125| parentSubTitle | [ResourceStr](ts-types.md#resourcestr) | Yes| Secondary text of the parent node.| 126| currentSubtitle | [ResourceStr](ts-types.md#resourcestr) | Yes| Secondary text of the current node.| 127 128## NodeParam 129 130**System capability**: SystemCapability.ArkUI.ArkUI.Full 131 132| Name| Type| Mandatory| Description | 133| -------- | -------- | -------- |--------------------------------------------------------------------------------------------------------------------------------------------------| 134| parentNodeId | number | No| Parent node.<br>The value must be greater than or equal to -1.<br>Default value: -1. The root node ID is -1. If the value is less than -1, the setting does not take effect.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 135| currentNodeId | number | No| Current child node.<br>The value must be greater than or equal to -1.<br>The value cannot be the root node ID, cannot be null, and cannot be duplicated.<br>Default value: **-1**<br>**Atomic service API**: This API can be used in atomic services since API version 11.| 136| isFolder | boolean | No| Whether the node is a directory.<br> Default value: **false**.<br> **true**: The node is a directory.<br>**false**: The node is not a directory.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 137| icon | [ResourceStr](ts-types.md#resourcestr) | No| Icon.<br>The default value is an empty string.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 138| symbolIconStyle<sup>18+</sup> | [SymbolGlyphModifier](ts-universal-attributes-attribute-modifier.md) | No| Symbol icon, which has higher priority than **icon**.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18. | 139| selectedIcon | [ResourceStr](ts-types.md#resourcestr) | No| Icon of the selected node.<br>The default value is an empty string.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 140| symbolSelectedIconStyle<sup>18+</sup> | [SymbolGlyphModifier](ts-universal-attributes-attribute-modifier.md) | No| Symbol icon of the selected node., which has higher priority than **selectedIcon**.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18. | 141| editIcon | [ResourceStr](ts-types.md#resourcestr) | No| Edit icon.<br>The default value is an empty string.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 142| symbolEditIconStyle<sup>18+</sup> | [SymbolGlyphModifier](ts-universal-attributes-attribute-modifier.md) | No| Symbol edit icon, which has a higher priority than **editIcon**.<br>Default value: **undefined**<br>**Atomic service API**: This API can be used in atomic services since API version 18. | 143| primaryTitle | [ResourceStr](ts-types.md#resourcestr) | No| Primary title.<br>The default value is an empty string.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 144| secondaryTitle | [ResourceStr](ts-types.md#resourcestr) | No| Secondary title.<br>The default value is an empty string.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 145| container | () => void | No| Right-click child component bound to the node. The child component is decorated with @Builder.<br>Default value: **() => void**.<br>**Atomic service API**: This API can be used in atomic services since API version 11. | 146 147 148## TreeListenerManager 149 150Implements a **TreeListenerManager** object, which can be bound to a **TreeView** component to listen for changes of tree nodes. One **TreeListenerManager** object can be bound to only one tree view component. 151 152 153### getInstance 154 155static getInstance(): TreeListenerManager 156 157Obtains a **TreeListenerManager** singleton object. 158 159**Atomic service API**: This API can be used in atomic services since API version 11. 160 161**System capability**: SystemCapability.ArkUI.ArkUI.Full 162 163**Return value** 164 165| Type | Description | 166| --------------- |------------------| 167| [TreeListenerManager](#treelistenermanager) | **TreeListenerManager** singleton object.| 168 169 170### getTreeListener 171 172getTreeListener(): TreeListener 173 174Obtains a listener. 175 176**Atomic service API**: This API can be used in atomic services since API version 11. 177 178**System capability**: SystemCapability.ArkUI.ArkUI.Full 179 180**Return value** 181 182| Type | Description | 183| ------------ |------------| 184| [TreeListener](#treelistener) | Obtained listener.| 185 186 187## TreeListener 188 189Listener of the tree view component. You can bind it to the **TreeView** component and use it to listen for changes of tree nodes. One listener can be bound to only one **TreeView** component. 190 191 192### on 193 194on(type: TreeListenType, callback: (callbackParam: CallbackParam) => void): void; 195 196Register a listener. 197 198**Atomic service API**: This API can be used in atomic services since API version 11. 199 200**System capability**: SystemCapability.ArkUI.ArkUI.Full 201 202| Name| Type| Mandatory| Description| 203| -------- | -------- | -------- | -------- | 204| type | [TreeListenType](#treelistentype) | Yes| Listening type.| 205| callback | (callbackParam: [CallbackParam](#callbackparam)) => void | Yes| Node information.| 206 207 208### once 209 210once(type: TreeListenType, callback: (callbackParam: CallbackParam) => void): void; 211 212Registers a one-off listener. 213 214**Atomic service API**: This API can be used in atomic services since API version 11. 215 216**System capability**: SystemCapability.ArkUI.ArkUI.Full 217 218| Name| Type| Mandatory| Description| 219| -------- | -------- | -------- | -------- | 220| type | [TreeListenType](#treelistentype) | Yes| Listening type.| 221| callback | (callbackParam: [CallbackParam](#callbackparam)) => void | Yes| Node information.| 222 223 224### off 225 226 227off(type: TreeListenType, callback?: (callbackParam: CallbackParam) => void): void; 228 229Unregisters a listener. 230 231**Atomic service API**: This API can be used in atomic services since API version 11. 232 233**System capability**: SystemCapability.ArkUI.ArkUI.Full 234 235 236| Name| Type| Mandatory| Description| 237| -------- | -------- | -------- | -------- | 238| type | [TreeListenType](#treelistentype) | Yes| Listening type.| 239| callback | (callbackParam: [CallbackParam](#callbackparam)) => void | No| Node information.| 240 241## TreeListenType 242 243**Atomic service API**: This API can be used in atomic services since API version 11. 244 245**System capability**: SystemCapability.ArkUI.ArkUI.Full 246 247| Name| Value| Description| 248| -------- | -------- | -------- | 249| NODE_CLICK | "NodeClick" | Listens for click events of nodes.| 250| NODE_ADD | "NodeAdd" | Listens for add events of nodes.| 251| NODE_DELETE | "NodeDelete" | Listens for delete events of nodes.| 252| NODE_MODIFY | "NodeModify" | Listens for modify events of nodes.| 253| NODE_MOVE | "NodeMove" | Listens for move events of nodes.| 254 255## CallbackParam 256 257**Atomic service API**: This API can be used in atomic services since API version 11. 258 259**System capability**: SystemCapability.ArkUI.ArkUI.Full 260 261| Name| Type| Mandatory| Description | 262| -------- | -------- | -------- |------------------------------------------| 263| currentNodeId | number | Yes| ID of the current child node.<br>The value must be greater than or equal to 0. | 264| parentNodeId | number | No| ID of the current parent node.<br>The value must be greater than or equal to -1.<br>Default value: **-1**| 265| childIndex | number | No| Child index.<br>The value must be greater than or equal to -1.<br>Default value: **-1** | 266 267## Events 268The [universal events](ts-component-general-events.md) are not supported. 269 270## Example 271 272### Example 1: Configuring a Simple Tree View 273 274This example showcases how to use **TreeController** to perform operations on tree nodes, such as adding, deleting, and renaming. It also demonstrates the effects of adding nodes with different parameters. 275 276```ts 277import { TreeController, TreeListener, TreeListenerManager, TreeListenType, NodeParam, TreeView, CallbackParam } from '@kit.ArkUI'; 278 279@Entry 280@Component 281struct TreeViewDemo { 282 private treeController: TreeController = new TreeController(); 283 private treeListener: TreeListener = TreeListenerManager.getInstance().getTreeListener(); 284 @State clickId: number = 0; 285 286 aboutToDisappear(): void { 287 this.treeListener.off(TreeListenType.NODE_CLICK, undefined); 288 this.treeListener.off(TreeListenType.NODE_ADD, undefined); 289 this.treeListener.off(TreeListenType.NODE_DELETE, undefined); 290 this.treeListener.off(TreeListenType.NODE_MOVE, undefined); 291 } 292 293 @Builder menuBuilder1() { 294 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 295 Text('Add').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 296 .onClick((event: ClickEvent) => { 297 this.treeController.addNode(); 298 }) 299 Divider() 300 Text('Delete').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 301 .onClick((event: ClickEvent) => { 302 this.treeController.removeNode(); 303 }) 304 Divider() 305 Text('Rename').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 306 .onClick((event: ClickEvent) => { 307 this.treeController.modifyNode(); 308 }) 309 }.width(100).border({width: 1, color: 0x80808a, radius: '16dp'}) 310 } 311 312 aboutToAppear(): void { 313 this.treeListener.on(TreeListenType.NODE_CLICK, (callbackParam: CallbackParam) => { 314 this.clickId = callbackParam.currentNodeId; 315 }) 316 this.treeListener.on(TreeListenType.NODE_ADD, (callbackParam: CallbackParam) => { 317 this.clickId = callbackParam.currentNodeId; 318 }) 319 this.treeListener.on(TreeListenType.NODE_DELETE, (callbackParam: CallbackParam) => { 320 this.clickId = callbackParam.currentNodeId; 321 }) 322 this.treeListener.once(TreeListenType.NODE_MOVE, (callbackParam: CallbackParam) => { 323 this.clickId = callbackParam.currentNodeId; 324 }) 325 326 let normalResource: Resource = $r('sys.media.ohos_ic_normal_white_grid_folder'); 327 let selectedResource: Resource = $r('sys.media.ohos_ic_public_select_all'); 328 let editResource: Resource = $r('sys.media.ohos_ic_public_edit'); 329 let nodeParam: NodeParam = { parentNodeId:-1, currentNodeId: 1, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 330 editIcon: editResource, primaryTitle: "Directory 1 to verify the adaptive effect", 331 secondaryTitle: "6" }; 332 this.treeController 333 .addNode(nodeParam) 334 .addNode({parentNodeId:1, currentNodeId: 2, isFolder: false, primaryTitle: "Project 1_1" }) 335 .addNode({ parentNodeId:-1, currentNodeId: 7, isFolder: true, primaryTitle: "Directory 2" }) 336 .addNode({ parentNodeId:-1, currentNodeId: 23, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 337 editIcon: editResource, primaryTitle: "Directory 3" }) 338 .addNode({ parentNodeId:-1, currentNodeId: 24, isFolder: false, primaryTitle: "Project 4" }) 339 .addNode({ parentNodeId:-1, currentNodeId: 31, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 340 editIcon: editResource, primaryTitle: "Directory 5", secondaryTitle: "0" }) 341 .addNode({ parentNodeId:-1, currentNodeId: 32, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 342 editIcon: editResource, primaryTitle: "Directory 6", secondaryTitle: "0" }) 343 .addNode({ parentNodeId:32, currentNodeId: 35, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 344 editIcon: editResource, primaryTitle: "Directory 6-1", secondaryTitle: "0" }) 345 .addNode({ parentNodeId:-1, currentNodeId: 33, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 346 editIcon: editResource, primaryTitle: "Directory 7", secondaryTitle: "0" }) 347 .addNode({ parentNodeId:33, currentNodeId: 34, isFolder: false, primaryTitle: "Project 8" }) 348 .addNode({ parentNodeId:-1, currentNodeId: 36, isFolder: false, primaryTitle: "Project 9" }) 349 .buildDone(); 350 this.treeController.refreshNode (-1, "Parent", "Child"); 351 } 352 353 build() { 354 Column(){ 355 SideBarContainer(SideBarContainerType.Embed) 356 { 357 TreeView({ treeController: this.treeController }) 358 Row() { 359 Divider().vertical(true).strokeWidth(2).color(0x000000).lineCap(LineCapStyle.Round) 360 Column({ space: 30 }) { 361 Text('ClickId=' + this.clickId).fontSize('16fp') 362 Button('Add', { type: ButtonType.Normal, stateEffect: true }) 363 .borderRadius(8).backgroundColor(0x317aff).width(90) 364 .onClick((event: ClickEvent) => { 365 this.treeController.addNode(); 366 }) 367 Button('Modify', { type: ButtonType.Normal, stateEffect: true }) 368 .borderRadius(8).backgroundColor(0x317aff).width(90) 369 .onClick((event: ClickEvent) => { 370 this.treeController.modifyNode(); 371 }) 372 Button('Remove', { type: ButtonType.Normal, stateEffect: true }) 373 .borderRadius(8).backgroundColor(0x317aff).width(120) 374 .onClick((event: ClickEvent) => { 375 this.treeController.removeNode(); 376 }) 377 }.height('100%').width('70%').alignItems(HorizontalAlign.Start).margin(10) 378 } 379 } 380 .focusable(true) 381 .showControlButton(false) 382 .showSideBar(true) 383 } 384 }} 385``` 386 387 388 389### Example 2: Setting the Symbol Icon 390 391This example demonstrates how to use **symbolIconStyle**, **symbolEditIconStyle**, and **symbolSelectedIconStyle** in **NodeParam** to set custom symbol icons. This functionality is supported since API version 18. 392 393```ts 394import { TreeController, TreeListener, TreeListenerManager, TreeListenType, NodeParam, TreeView, CallbackParam, 395 SymbolGlyphModifier } from '@kit.ArkUI'; 396 397@Entry 398@Component 399struct TreeViewDemo { 400 private treeController: TreeController = new TreeController(); 401 private treeListener: TreeListener = TreeListenerManager.getInstance().getTreeListener(); 402 @State clickNodeId: number = 0; 403 404 aboutToDisappear(): void { 405 this.treeListener.off(TreeListenType.NODE_CLICK, undefined); 406 this.treeListener.off(TreeListenType.NODE_ADD, undefined); 407 this.treeListener.off(TreeListenType.NODE_DELETE, undefined); 408 this.treeListener.off(TreeListenType.NODE_MOVE, undefined); 409 } 410 411 @Builder menuBuilder1() { 412 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 413 Text('Add').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 414 .onClick((event: ClickEvent) => { 415 this.treeController.addNode(); 416 }) 417 Divider() 418 Text('Delete').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 419 .onClick((event: ClickEvent) => { 420 this.treeController.removeNode(); 421 }) 422 Divider() 423 Text('Rename').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 424 .onClick((event: ClickEvent) => { 425 this.treeController.modifyNode(); 426 }) 427 }.width(100).border({width: 1, color: 0x80808a, radius: '16dp'}) 428 } 429 430 aboutToAppear(): void { 431 this.treeListener.on(TreeListenType.NODE_CLICK, (callbackParam: CallbackParam) => { 432 this.clickNodeId = callbackParam.currentNodeId; 433 }) 434 this.treeListener.on(TreeListenType.NODE_ADD, (callbackParam: CallbackParam) => { 435 this.clickNodeId = callbackParam.currentNodeId; 436 }) 437 this.treeListener.on(TreeListenType.NODE_DELETE, (callbackParam: CallbackParam) => { 438 this.clickNodeId = callbackParam.currentNodeId; 439 }) 440 this.treeListener.once(TreeListenType.NODE_MOVE, (callbackParam: CallbackParam) => { 441 this.clickNodeId = callbackParam.currentNodeId; 442 }) 443 444 let normalResource: Resource = $r('sys.symbol.house'); 445 let selectedResource: Resource = $r('sys.symbol.car'); 446 let editResource: Resource = $r('sys.symbol.calendar'); 447 let normalSymbolResource: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.bell')).fontColor([Color.Red]); 448 let selectedSymbolResource: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.heart')).fontColor([Color.Blue]); 449 let editSymbolResource: SymbolGlyphModifier = new SymbolGlyphModifier($r('sys.symbol.cake')).fontColor([Color.Pink]); 450 let nodeParam: NodeParam = { parentNodeId:-1, currentNodeId: 1, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 451 editIcon: editResource, primaryTitle: "Directory 1", 452 secondaryTitle: "6" }; 453 this.treeController 454 .addNode(nodeParam) 455 .addNode({parentNodeId:1, currentNodeId: 2, isFolder: false, primaryTitle: "Project 1_1" }) 456 .addNode({ parentNodeId:-1, currentNodeId: 7, isFolder: true, primaryTitle: "Directory 2" }) 457 .addNode({ parentNodeId:-1, currentNodeId: 23, isFolder: true, icon: normalResource, symbolIconStyle: normalSymbolResource, 458 selectedIcon: selectedResource, symbolSelectedIconStyle: selectedSymbolResource, editIcon: editResource, 459 symbolEditIconStyle: editSymbolResource, primaryTitle: "Directory 3" }) 460 .addNode({ parentNodeId:-1, currentNodeId: 24, isFolder: false, primaryTitle: "Project 4" }) 461 .addNode({ parentNodeId:-1, currentNodeId: 31, isFolder: true, icon: normalResource, symbolIconStyle: normalSymbolResource, 462 selectedIcon: selectedResource, symbolSelectedIconStyle: selectedSymbolResource, editIcon: editResource, 463 symbolEditIconStyle: editSymbolResource, primaryTitle: "Directory 5", secondaryTitle: "0" }) 464 .addNode({ parentNodeId:-1, currentNodeId: 32, isFolder: true, icon: normalResource, symbolIconStyle: normalSymbolResource, 465 selectedIcon: selectedResource, symbolSelectedIconStyle: selectedSymbolResource, editIcon: editResource, 466 symbolEditIconStyle: editSymbolResource, primaryTitle: "Directory 6", secondaryTitle: "0" }) 467 .addNode({ parentNodeId:32, currentNodeId: 35, isFolder: true, icon: normalResource, symbolIconStyle: normalSymbolResource, 468 selectedIcon: selectedResource, symbolSelectedIconStyle: selectedSymbolResource, editIcon: editResource, 469 symbolEditIconStyle: editSymbolResource, primaryTitle: "Directory 6-1", secondaryTitle: "0" }) 470 .addNode({ parentNodeId:-1, currentNodeId: 33, isFolder: true, icon: normalResource, symbolIconStyle: normalSymbolResource, 471 selectedIcon: selectedResource, symbolSelectedIconStyle: selectedSymbolResource, editIcon: editResource, 472 symbolEditIconStyle: editSymbolResource, primaryTitle: "Directory 7", secondaryTitle: "0" }) 473 .addNode({ parentNodeId:33, currentNodeId: 34, isFolder: false, primaryTitle: "Project 8" }) 474 .addNode({ parentNodeId:-1, currentNodeId: 36, isFolder: false, primaryTitle: "Project 9" }) 475 .buildDone(); 476 this.treeController.refreshNode (-1, "Parent", "Child"); 477 } 478 479 build() { 480 Column(){ 481 SideBarContainer(SideBarContainerType.Embed) 482 { 483 TreeView({ treeController: this.treeController }) 484 Row() { 485 Divider().vertical(true).strokeWidth(2).color(0x000000).lineCap(LineCapStyle.Round) 486 Column({ space: 30 }) { 487 Text('ClickNodeId=' + this.clickNodeId).fontSize('16fp') 488 Button('Add', { type: ButtonType.Normal, stateEffect: true }) 489 .borderRadius(8).backgroundColor(0x317aff).width(90) 490 .onClick((event: ClickEvent) => { 491 this.treeController.addNode(); 492 }) 493 Button('Modify', { type: ButtonType.Normal, stateEffect: true }) 494 .borderRadius(8).backgroundColor(0x317aff).width(90) 495 .onClick((event: ClickEvent) => { 496 this.treeController.modifyNode(); 497 }) 498 Button('Remove', { type: ButtonType.Normal, stateEffect: true }) 499 .borderRadius(8).backgroundColor(0x317aff).width(120) 500 .onClick((event: ClickEvent) => { 501 this.treeController.removeNode(); 502 }) 503 }.height('100%').width('80%').alignItems(HorizontalAlign.Start).margin(10) 504 } 505 } 506 .focusable(true) 507 .showControlButton(false) 508 .showSideBar(true) 509 } 510 }} 511``` 512 513 514