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