1# TreeView 2 3 4树视图作为一种分层显示的列表,适合显示嵌套结构。拥有父列表项和子列表项,可展开或折叠。子列表项支持选中一项或多项。 5 6 7用于效率型应用,如备忘录、电子邮件、图库中的侧边导航栏中。 8 9 10>  **说明:** 11> 该组件从API Version 10开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 12 13 14## 导入模块 15 16``` 17import { TreeView } from "@ohos.arkui.advanced.TreeView" 18``` 19 20 21## 子组件 22 23无 24 25 26## 接口 27 28TreeView({ treeController: TreeController }) 29 30**装饰器类型:**\@Component 31 32**系统能力:** SystemCapability.ArkUI.ArkUI.Full 33 34 35**参数:** 36 37 38| 参数名 | 参数类型 | 必填 | 参数描述 | 39| -------- | -------- | -------- | -------- | 40| treeController | [TreeController](#treecontroller) | 是 | 树视图节点信息。 | 41 42 43## TreeController 44 45树视图组件的控制器,可以将此对象绑定至树视图组件,然后通过它控制树的节点信息,同一个控制器不可以控制多个树视图组件。 46 47 48### 导入对象 49 50``` 51treeController: TreeController = new TreeController() 52``` 53 54 55### addNode 56 57 58addNode(nodeParam?: NodeParam): void 59 60 61点击某个节点后,调用该方法可以触发新增孩子节点 62 63 64**参数:** 65 66 67| 参数名 | 参数类型 | 必填 | 参数描述 | 68| -------- | -------- | -------- | -------- | 69| nodeParam | [NodeParam](#nodeparam) | 否 | 节点信息。 | 70 71 72### removeNode 73 74removeNode(): void 75 76点击某个节点后,调用该方法可以触发删除该节点 77 78 79### modifyNode 80 81 82modifyNode(): void 83 84 85点击某个节点后,调用该方法可以触发修改该节点 86 87 88### buildDone 89 90buildDone(): void 91 92建立树视图。节点增加完毕后,必须调用该方法,触发树信息的保存 93 94 95### refreshNode 96 97refreshNode(parentId: number, parentSubTitle: ResourceStr, currentSubtitle: ResourceStr): void 98 99**参数:** 100 101| 参数名 | 参数类型 | 必填 | 参数描述 | 102| -------- | -------- | -------- | -------- | 103| parentId | number | 是 | 父节点Id。 | 104| parentSubTitle | ResourceStr | 是 | 父节点副文本 | 105| currentSubtitle | ResourceStr | 是 | 当前节点副文本 | 106 107 108## NodeParam 109 110| 名称 | 值 | 是否必填 | 描述 | 111| -------- | -------- | -------- | -------- | 112| parentNodeId | number | 否 | 父亲节点 | 113| currentNodeId | number | 否 | 当前孩子节点 | 114| isFolder | boolean | 否 | 是否是目录 | 115| icon | ResourceStr | 否 | 图标 | 116| selectedIcon | ResourceStr | 否 | 选中图标 | 117| editIcon | ResourceStr | 否 | 编辑图标 | 118| primaryTitle | ResourceStr | 否 | 主标题 | 119| secondaryTitle | ResourceStr | 否 | 副标题 | 120| container | () => void | 否 | 绑定在节点上的子组件,子组件由[@Builder](https://docs.openharmony.cn/pages/v3.1/en/application-dev/ui/ts-component-based-builder.md/)修饰 | 121 122 123## TreeListenerManager对象说明 124 125树视图组件的监听器,可以将此对象绑定至树视图组件,然后通过它监听树的节点的变化,同一个监听器不可以控制多个树视图组件。 126 127 128### 导入对象 129 130``` 131import { TreeListenerManager } from '@ohos.arkui.advanced.TreeView' 132``` 133 134 135### getInstance 136 137getInstance(): TreeListenerManager 138 139获取监听管理器单例对象 140 141 142### getTreeListener() 143 144getTreeListener(): TreeListener 145 146获取监听器 147 148 149## TreeListener对象说明 150 151树视图组件的监听器,可以将此对象绑定至树视图组件,然后通过它监听树的节点的变化,同一个监听器不可以控制多个树视图组件。 152 153 154### 导入对象 155 156``` 157treeListener: TreeListener = TreeListenerManager.getInstance().getTreeListener() 158``` 159 160 161### on 162 163on(type: TreeListenType, callback: (callbackParam: CallbackParam) => void): void; 164 165注册监听 166 167**参数:** 168 169| 参数名 | 参数类型 | 必填 | 参数描述 | 170| -------- | -------- | -------- | -------- | 171| type | [TreeListenType](#treelistentype) | 是 | 监听类型 | 172| nodeParam | [NodeParam](#nodeparam) | 是 | 节点信息。 | 173 174 175### once 176 177once(type: TreeListenType, callback: (callbackParam: CallbackParam) => void): void; 178 179注册一次监听 180 181**参数:** 182 183| 参数名 | 参数类型 | 必填 | 参数描述 | 184| -------- | -------- | -------- | -------- | 185| type | [TreeListenType](#treelistentype) | 是 | 监听类型 | 186| nodeParam | [NodeParam](#nodeparam) | 是 | 节点信息。 | 187 188 189### off 190 191 192off(type: TreeListenType, callback?: (callbackParam: CallbackParam) => void): void; 193 194 195取消监听 196 197 198**参数:** 199 200 201| 参数名 | 参数类型 | 必填 | 参数描述 | 202| -------- | -------- | -------- | -------- | 203| type | [TreeListenType](#treelistentype) | 是 | 监听类型 | 204| nodeParam | [NodeParam](#nodeparam) | 是 | 节点信息。 | 205 206 207## TreeListenType 208 209| 名称 | 描述 | 210| -------- | -------- | 211| NODE_CLICK | 监听节点点击事件 | 212| NODE_ADD | 监听节点增加事件 | 213| NODE_DELETE | 监听节点删除事件 | 214| NODE_MODIFY | 监听节点修改事件 | 215| NODE_MOVE | 监听节点移动事件 | 216 217 218## CallbackParam 219 220| 名称 | 值 | 是否必填 | 描述 | 221| -------- | -------- | -------- | -------- | 222| currentNodeId | number | 是 | 当前孩子节点 | 223| parentNodeId | number | 否 | 父亲节点表 | 224| childIndex: number | number | 否 | 孩子索引 | 225 226 227## 示例 228 229``` 230import { TreeController, TreeListener, TreeListenerManager, TreeListenType, NodeParam, TreeView, CallbackParam } from '@ohos.arkui.advanced.TreeView' 231 232@Entry 233@Component 234struct TreeViewDemo { 235 private listTreeNode: TreeController = new TreeController(); 236 private appEventBus: TreeListener = TreeListenerManager.getInstance().getTreeListener(); 237 @State clickNodeId: number = 0; 238 @State numbers: string[] = ['one', 'two', 'three', 'four', 'five', 'six']; 239 240 aboutToDisappear(): void { 241 this.appEventBus.off(TreeListenType.NODE_CLICK, null); 242 this.appEventBus.off(TreeListenType.NODE_ADD, null); 243 this.appEventBus.off(TreeListenType.NODE_DELETE, null); 244 } 245 246 @Builder menuBuilder0() { 247 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 248 Text('删除').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 249 .onClick((event: ClickEvent) => { 250 this.listTreeNode.removeNode(); 251 }) 252 }.width(100).border({width: 1, color: 0x80808a, radius: '16dp'}) 253 } 254 255 @Builder menuBuilder1() { 256 Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) { 257 Text('新增').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 258 .onClick((event: ClickEvent) => { 259 this.listTreeNode.addNode(); 260 }) 261 Divider() 262 Text('删除').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 263 .onClick((event: ClickEvent) => { 264 this.listTreeNode.removeNode(); 265 }) 266 Divider() 267 Text('重命名').fontSize(16).width(100).height(30).textAlign(TextAlign.Center) 268 .onClick((event: ClickEvent) => { 269 this.listTreeNode.modifyNode(); 270 }) 271 }.width(100).border({width: 1, color: 0x80808a, radius: '16dp'}) 272 } 273 274 aboutToAppear(): void { 275 this.appEventBus.on(TreeListenType.NODE_MOVE, (callbackParam: CallbackParam) => { 276 }) 277 this.appEventBus.on(TreeListenType.NODE_CLICK, (callbackParam: CallbackParam) => { 278 }) 279 280 let normalResource: Resource = $r('app.media.ic_public_collect_normal'); 281 let selectedResource: Resource = $r('app.media.ic_public_collect_selected'); 282 let editResource: Resource = $r('app.media.ic_public_collect_edit'); 283 let nodeParam: NodeParam = { parentNodeId:-1, currentNodeId: 1, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 284 editIcon: editResource, primaryTitle: "目录1验证悬浮框自适应效果是否OK", 285 menu: this.menuBuilder1.bind(this), secondaryTitle: "6" }; 286 this.listTreeNode 287 .addNode(nodeParam) 288 .addNode({parentNodeId:1, currentNodeId: 2, isFolder: false, primaryTitle: "项目1_1" }) 289 .addNode({ parentNodeId:-1, currentNodeId: 7, isFolder: true, primaryTitle: "目录2", menu: this.menuBuilder1.bind(this) }) 290 .addNode({ parentNodeId:-1, currentNodeId: 23, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 291 editIcon: editResource, primaryTitle: "目录3", menu: this.menuBuilder1.bind(this) }) 292 .addNode({ parentNodeId:-1, currentNodeId: 24, isFolder: false, primaryTitle: "项目4", menu: this.menuBuilder1.bind(this) }) 293 .addNode({ parentNodeId:-1, currentNodeId: 31, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 294 editIcon: editResource, primaryTitle: "目录5", menu: this.menuBuilder1.bind(this), secondaryTitle: "0" }) 295 .addNode({ parentNodeId:-1, currentNodeId: 32, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 296 editIcon: editResource, primaryTitle: "目录6", menu: this.menuBuilder1.bind(this), secondaryTitle: "0" }) 297 .addNode({ parentNodeId:32, currentNodeId: 35, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 298 editIcon: editResource, primaryTitle: "目录6-1", menu: this.menuBuilder1.bind(this), secondaryTitle: "0" }) 299 .addNode({ parentNodeId:-1, currentNodeId: 33, isFolder: true, icon: normalResource, selectedIcon: selectedResource, 300 editIcon: editResource, primaryTitle: "目录7", menu: this.menuBuilder1.bind(this), secondaryTitle: "0" }) 301 .addNode({ parentNodeId:33, currentNodeId: 34, isFolder: false, primaryTitle: "项目8" }) 302 .addNode({ parentNodeId:-1, currentNodeId: 36, isFolder: false, primaryTitle: "项目9" }) 303 .buildDone(); 304 } 305 306 @Builder subfieldPopup(item: any) { 307 Column() { 308 Text(item) 309 .width('50%').height(60).fontSize(16).borderRadius(10) 310 .textAlign(TextAlign.Center).backgroundColor(Color.Yellow) 311 } 312 } 313 314 build() { 315 SideBarContainer(SideBarContainerType.Embed) 316 { 317 TreeView({ treeController: this.listTreeNode }) 318 Row() { 319 Divider().vertical(true).strokeWidth(2).color(0x000000).lineCap(LineCapStyle.Round) 320 Column() { 321 Row() { 322 Text('ClickNodeId=' + this.clickNodeId).fontSize('16fp') 323 Button('Add', { type: ButtonType.Normal, stateEffect: true }) 324 .borderRadius(8).backgroundColor(0x317aff).width(90) 325 .onClick((event: ClickEvent) => { 326 this.listTreeNode.addNode(); 327 }) 328 Button('Modify', { type: ButtonType.Normal, stateEffect: true }) 329 .borderRadius(8).backgroundColor(0x317aff).width(90) 330 .onClick((event: ClickEvent) => { 331 this.listTreeNode.modifyNode(); 332 }) 333 Button('Remove', { type: ButtonType.Normal, stateEffect: true }) 334 .borderRadius(8).backgroundColor(0x317aff).width(120) 335 .onClick((event: ClickEvent) => { 336 this.listTreeNode.removeNode(); 337 }) 338 } 339 340 /* drag item. */ 341 List({ space: 10, initialIndex: 0 }) { 342 ForEach(this.numbers, (item) => { 343 ListItem() { 344 Text('' + item) 345 .width('100%').height(38).fontSize(16).borderRadius(10) 346 .textAlign(TextAlign.Center).backgroundColor(0xAFEEEE) 347 } 348 .onSelect((isSelected: boolean) => { 349 console.log('listItem selected') 350 }) 351 .onDragStart(() => { 352 this.listTreeNode.refreshNode(1,'选择节点','目标节点') 353 return this.subfieldPopup(item) 354 }) 355 }, item => item) 356 } 357 .editMode(true) 358 .multiSelectable(true) 359 .onDrop((event: DragEvent, extraParams: string) => { 360 console.log('outer onDrop') 361 }) 362 363 }.height('100%').width('70%').alignItems(HorizontalAlign.Start) 364 } 365 } 366 .focusable(true) 367 .sideBarWidth(240) 368 .minSideBarWidth(0) 369 .maxSideBarWidth(900) 370 .showControlButton(false) 371 .showSideBar(true) 372 .onChange((value: boolean) => { 373 console.info('status:' + value); 374 }) 375 } 376} 377``` 378 379 380