1# ArkUI组件开发常见问题(ArkTS) 2 3 4## 自定义弹窗能否在ts文件中定义和使用(API 9) 5 6自定义弹窗的定义和初始化需要用到属于ArkTS语法内容,必须在ets后缀文件中定义使用,不能在ts后缀文件中定义使用。 7 8**参考链接** 9 10[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 11 12 13## 自定义弹窗中的变量如何传递给页面(API 9) 14 15**问题现象** 16 17在自定义弹窗内定义的变量内容,在关闭弹窗或变量变化时需要及时传递给页面,可以通过何种方式传递? 18 19**解决措施** 20 21- 方式一:使用组件的状态变量传递。 22 23- 方式二:在初始化弹窗时,传递一个方法给自定义弹窗,在自定义弹窗中触发该方法,弹窗中变量作为方法的参数。 24 25- 方式三:使用AppStorage或LocalStorage方式管理页面状态,实现自定义弹窗和页面之间状态的共享。 26 27**代码示例** 28 29- 方式一: 30 31 ``` 32 @CustomDialog 33 struct CustomDialog01 { 34 @Link inputValue: string 35 controller: CustomDialogController 36 build() { 37 Column() { 38 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 39 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 40 .onChange((value: string) => { 41 this.inputValue = value 42 }) 43 } 44 } 45 } 46 47 @Entry 48 @Component 49 struct DialogDemo01 { 50 @State inputValue: string = 'click me' 51 dialogController: CustomDialogController = new CustomDialogController({ 52 builder: CustomDialog01({ 53 inputValue: $inputValue 54 }) 55 }) 56 57 build() { 58 Column() { 59 Button(this.inputValue) 60 .onClick(() => { 61 this.dialogController.open() 62 }).backgroundColor(0x317aff) 63 }.width('100%').margin({ top: 5 }) 64 } 65 } 66 ``` 67 68- 方式二: 69 70 ``` 71 @CustomDialog 72 struct CustomDialog02 { 73 private inputValue: string 74 changeInputValue: (val: string) => void 75 controller: CustomDialogController 76 build() { 77 Column() { 78 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 79 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 80 .onChange((value: string) => { 81 this.changeInputValue(value) 82 }) 83 } 84 } 85 } 86 87 @Entry 88 @Component 89 struct DialogDemo02 { 90 @State inputValue: string = 'click me' 91 dialogController: CustomDialogController = new CustomDialogController({ 92 builder: CustomDialog02({ 93 inputValue: this.inputValue, 94 changeInputValue: (val: string) => { 95 this.inputValue = val 96 } 97 }) 98 }) 99 100 build() { 101 Column() { 102 Button(this.inputValue) 103 .onClick(() => { 104 this.dialogController.open() 105 }).backgroundColor(0x317aff) 106 }.width('100%').margin({ top: 5 }) 107 } 108 } 109 ``` 110 111- 方式三: 112 113 ``` 114 let storage = LocalStorage.GetShared() 115 @CustomDialog 116 struct CustomDialog03 { 117 @LocalStorageLink('inputVal') inputValue: string = '' 118 controller: CustomDialogController 119 build() { 120 Column() { 121 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 122 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 123 .onChange((value: string) => { 124 this.inputValue = value; 125 }) 126 } 127 } 128 } 129 130 @Entry(storage) 131 @Component 132 struct DialogDemo03 { 133 @LocalStorageLink('inputVal') inputValue: string = '' 134 dialogController: CustomDialogController = new CustomDialogController({ 135 builder: CustomDialog03() 136 }) 137 138 build() { 139 Column() { 140 Button(this.inputValue) 141 .onClick(() => { 142 this.dialogController.open() 143 }).backgroundColor(0x317aff) 144 }.width('100%').margin({ top: 5 }) 145 } 146 } 147 ``` 148 149 150## 如何获取组件的宽高(API 9) 151 152**问题现象** 153 154组件的宽高信息用于计算布局区域大小以及偏移量等内容,如何获取宽高信息? 155 156**解决措施** 157 158- 方式一:使用组件区域变化事件onAreaChange,在组件初始化或组件尺寸发生变化时触发。 159 160- 方式二:在点击或触摸事件中,事件的回调信息中存在目标元素的区域信息。 161 162**参考链接** 163 164[组件区域变化事件](../reference/apis-arkui/arkui-ts/ts-universal-component-area-change-event.md),[点击事件](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md),[触摸事件](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) 165 166 167## 如何一键清空TextInput、TextArea组件内容(API 9) 168 169**问题现象** 170 171TextInput,TextArea组件输入多字符后,需要实现点击清空。 172 173**解决措施** 174 175将状态变量赋值给TextInput或TextArea组件的text属性,在做点击清空事件时为状态变量赋值空字符串。 176 177**代码示例** 178 179```ts 180// xxx.ets 181@Entry 182@Component 183struct Index { 184 @State text: string = 'Hello World'; 185 controller: TextInputController = new TextInputController(); 186 187 build() { 188 Row() { 189 Column() { 190 TextInput({ 191 placeholder: 'Please input your words.', text: this.text, 192 controller: this.controller 193 }).onChange((value: string) => { 194 this.text = value; 195 }) 196 Button("Clear TextInput").onClick(() => { 197 this.text = ""; 198 }) 199 } 200 .width('100%') 201 } 202 .height('100%') 203 } 204} 205``` 206 207 208## 如何设置自定义弹窗位置(API 9) 209 210**问题现象** 211 212自定义弹窗当前默认在窗口居中显示,当自定义弹窗需要与窗口边框对齐是需要设置自定义弹窗的对齐方式。 213 214**解决措施** 215 216初始化自定义弹窗时,通过alignment参数设置对齐方式,通过offset设置弹窗偏移量。 217 218**参考链接** 219 220[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 221 222 223## 如何隐藏容器组件的溢出内容(API 9) 224 225**问题现象** 226 227当容器组件内容溢出时,表现为子组件边缘超出容器组件,需要进行隐藏设置。 228 229**解决措施** 230 231将通用属性-形状裁剪clip属性设置为true,表示按照容器边缘轮廓进行裁剪。此属性默认为false,表示不进行裁剪隐藏。 232 233**参考链接** 234 235[形状裁剪](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sharp-clipping.md) 236 237 238## 自定义弹窗大小如何自适应内容(API 9) 239 240**问题现象** 241 242当自定义弹窗中存在可变化区域大小的子组件时,弹窗大小需要跟随自适应。 243 244**解决措施** 245 246- 方式一:采用弹窗容器默认样式。在默认样式中,弹窗容器高度自适应子节点,最大可为窗口高度的90%;弹窗容器的宽度根据栅格系统自适应,不跟随子节点变化。 247 248- 方式二:当显示设置customStyle为true时,弹窗宽高跟随子节点内容适应。 249 250**参考链接** 251 252[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 253 254 255## 如何理解自定义弹窗中的gridCount参数(API 9) 256 257gridCount参数是指弹窗宽度占栅格列数的个数。系统把窗口宽等分,等分的份数即为栅格列数,不同设备栅格列数不同。假设设备屏幕密度值在320vp<=水平宽度<600vp,所以栅格列数是4,则gridCount的有效值在[1, 4]。 258 259注意:仅采用弹窗默认样式时设置有效。 260 261**参考链接** 262 263[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 264 265 266## 如何去除自定义弹窗的白色背景(API 9) 267 268**问题现象** 269 270使用自定义弹窗时,默认样式中存在白色背景。 271 272**解决措施** 273 274需要采用自定义样式来消除自定义弹窗的白色背景: 275 2761. 在初始化自定义弹窗时设置customStyle为true。 277 2782. 在定义弹窗时设置组件背景色backgroundColor。 279 280**参考链接** 281 282[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 283 284 285## TextInput组件密码模式下,右边的眼睛图标能否支持自定义(API 9) 286 287**问题现象** 288 289TextInput组件设置type为InputType.Password时,右侧出现眼睛图标,不能修改图标样式。 290 291**解决措施** 292 293当前图标不支持自定义,可使用TextInput的showPasswordIcon属性隐藏图标,使用Image组件替代控制TextInput组件的type。 294 295**参考链接** 296 297[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 298 299 300## TextInput的onSubmit事件如何使用(API 9) 301 302**问题现象** 303 304TextInput的onSubmit事件怎么触发,以及事件回调的参数类型代表的含义。 305 306**解决措施** 307 308onSubmit事件在外接键盘或软键盘回车时触发该回调,回调的参数为当前软键盘回车键类型。通过TextInput的enterKeyType属性可以设置输入法回车键类型,软键盘回车键样式需要输入法的支持。 309 310**参考链接** 311 312[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 313 314 315## TextInput在聚焦时如何使光标回到起点(API 9) 316 317**问题现象** 318 319TextInput组件在聚焦时,光标位置会自动根据触摸点位置变化,如何使得聚焦时光标固定显示在起点位置? 320 321**解决措施** 322 3231. TextInput组件绑定onEditChange事件,该事件TextInput可进行输入时触发。 324 3252. 在事件回调用TextInputController.caretPosition方法设置光标位置,不过需要用到setTimeout延迟方法。 326 327**代码示例** 328 329``` 330@Entry 331@Component 332struct TextInputDemo { 333 controller: TextInputController = new TextInputController() 334 335 build() { 336 Column() { 337 TextInput({ controller: this.controller }) 338 .onEditChange((isEditing: boolean) => { 339 if (isEditing) { 340 setTimeout(() => { 341 this.controller.caretPosition(0) 342 }, 100) 343 } 344 }) 345 } 346 } 347} 348``` 349 350**参考链接** 351 352[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 353 354 355## 如何获取可滚动组件的当前滚动偏移量(API 9) 356 357**问题现象** 358 359可滚动组件包含List,Grid,Scroll等,在发生滚动时如何获取滚动偏移量? 360 361**解决措施** 362 3631. 可滚动组件在初始化时可设置scroller参数,绑定滚动控制器。 364 3652. 通过控制器的currentOffset方法可获取水平和竖直方向的滚动偏移量。 366 367**参考链接** 368 369[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#currentoffset) 370 371 372## 如何实现文本竖向排列(API 9) 373 374**问题现象** 375 376使用Text组件时,无法将文本排列方向设置为竖向排列。 377 378**解决措施** 379 380Text组件当前文本排列方向固定为横向排列,要设置为竖向排列,可将文件拆分,使用Flex容器组件装填,设置主轴方向为竖向。 381 382**代码示例** 383 384``` 385@Entry 386@Component 387struct Index15 { 388 private message: string = '本文档适用于应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉应用开发流程。'; 389 build() { 390 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 391 ForEach(this.message.split(''), (item, index) => { 392 Text(item) 393 .fontSize(30) 394 .flexShrink(0) 395 }) 396 } 397 } 398} 399``` 400 401 402## 如何将Ability的UI界面设置成透明(API 9) 403 404**问题现象** 405 406如何设置Ability的UI界面为透明 407 408**解决措施** 409 410将最上层容器组件背景色设置为透明,然后通过设置XComponent组件的opacity属性值为0.01来实现。 411 412示例: 413 414``` 415build() { 416 Stack() { 417 XComponent({ 418 id: 'componentId', 419 type: 'surface', 420 }) 421 .width('100%') 422 .height('100%') 423 .opacity(0.01) 424 // 页面内容 425 } 426 .width('100%') 427 .height('100%') 428 .backgroundColor('rgba(255,255,255, 0)') 429} 430``` 431 432 433## constraintSize尺寸设置不生效(API 9) 434 435适用于Stage模型。 436 437**问题现象** 438 439constraintSize约束组件尺寸时,子组件内设置百分比宽度,例如width('100%')会采用constraintSize约束中的最大宽乘百分比,导致撑开组件,看起来constraintSize设置没生效。 440 441**解决措施** 442 443可以在外层使用Scroll组件,设置constraintSize,当子组件占用空间超过设置的约束值时,会显示滚动条。 444 445 446## 如何将背景颜色设置为透明(API 9) 447 448**解决措施** 449 450将backgroundColor设置为 '\#00000000'。 451 452 453## Scroll组件滚动到达不了最底部(API 9) 454 455适用于Stage模型。 456 457**问题现象** 458 459Scroll组件在未设置高度情况下,默认为窗口高度,当滚动区域外存在其他组件时,滚动底部区域会出现遮挡。 460 461**解决措施** 462 463Scroll组件需要设置Scroll高度,或者使用Flex布局限制Scroll高度。 464 465 466## 如何自定义Video组件控制栏样式(API 9) 467 468适用于Stage模型。 469 470**解决措施** 471 4721. 通过设置属性controls为false关闭默认控制栏。 473 4742. 设置Video组件的controller。 475 4763. 通过ArkTS实现自定义的控制栏,并通过VideoController控制视频播放。 477 478**代码示例** 479 480```ts 481// xxx.ets 482@Entry 483@Component 484struct VideoCreateComponent { 485 @State videoSrc: Resource = $rawfile('video1.mp4') 486 @State previewUri: Resource = $r('app.media.poster1') 487 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 488 @State isAutoPlay: boolean = false 489 @State showControls: boolean = false 490 controller: VideoController = new VideoController() 491 492 build() { 493 Column() { 494 Video({ 495 src: this.videoSrc, 496 previewUri: this.previewUri, 497 currentProgressRate: this.curRate, 498 controller: this.controller 499 }) 500 .width('100%') 501 .height(600) 502 .autoPlay(this.isAutoPlay) 503 .controls(this.showControls) 504 .onStart(() => { 505 console.info('onStart') 506 }) 507 .onPause(() => { 508 console.info('onPause') 509 }) 510 .onFinish(() => { 511 console.info('onFinish') 512 }) 513 .onError(() => { 514 console.info('onError') 515 }) 516 .onPrepared((e) => { 517 console.info('onPrepared is ' + e.duration) 518 }) 519 .onSeeking((e) => { 520 console.info('onSeeking is ' + e.time) 521 }) 522 .onSeeked((e) => { 523 console.info('onSeeked is ' + e.time) 524 }) 525 .onUpdate((e) => { 526 console.info('onUpdate is ' + e.time) 527 }) 528 Row() { 529 Button('src').onClick(() => { 530 this.videoSrc = $rawfile('video2.mp4') // 切换视频源 531 }).margin(5) 532 Button('previewUri').onClick(() => { 533 this.previewUri = $r('app.media.poster2') // 切换视频预览海报 534 }).margin(5) 535 536 Button('controls').onClick(() => { 537 this.showControls = !this.showControls // 切换是否显示视频控制栏 538 }).margin(5) 539 } 540 541 Row() { 542 Button('start').onClick(() => { 543 this.controller.start() // 开始播放 544 }).margin(5) 545 Button('pause').onClick(() => { 546 this.controller.pause() // 暂停播放 547 }).margin(5) 548 Button('stop').onClick(() => { 549 this.controller.stop() // 结束播放 550 }).margin(5) 551 Button('setTime').onClick(() => { 552 this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置 553 }).margin(5) 554 } 555 556 Row() { 557 Button('rate 0.75').onClick(() => { 558 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放 559 }).margin(5) 560 Button('rate 1').onClick(() => { 561 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放 562 }).margin(5) 563 Button('rate 2').onClick(() => { 564 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放 565 }).margin(5) 566 } 567 } 568 } 569} 570``` 571 572**参考链接** 573 574[Video](../reference/apis-arkui/arkui-ts/ts-media-components-video.md#start) 575 576## 如何设置组件不同状态下的样式(API 9) 577 578**问题现象** 579 580对应组件的不同状态(如无状态、按下、禁用、聚焦、点击),显示不同的样式。 581 582**解决措施** 583 584使用多态样式,在组件的StateStyles接口中,定义组件不同状态下的样式。 585 586**代码示例** 587 588``` 589//xxx.ts 590@Entry 591@Component 592struct StyleExample { 593 @State isEnable: boolean = true; 594 595 @Styles pressedStyles() { 596 .backgroundColor("#ED6F21") 597 .borderRadius(10) 598 .borderStyle(BorderStyle.Dashed) 599 .borderWidth(2) 600 .borderColor('#33000000') 601 .width(120) 602 .height(30) 603 .opacity(1) 604 } 605 build() { 606 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 607 Text("pressed") 608 .backgroundColor('#0A59F7') 609 .borderRadius(20) 610 .borderStyle(BorderStyle.Dotted) 611 .borderWidth(2) 612 .borderColor(Color.Red) 613 .width(100) 614 .height(25) 615 .opacity(1) 616 .fontSize(14) 617 .fontColor(Color.White) 618 .stateStyles({ 619 pressed: this.pressedStyles 620 }) 621 .margin({ 622 bottom: 20 623 }) 624 .textAlign(TextAlign.Center) 625 } 626 .width(350) 627 .height(300) 628 } 629} 630``` 631 632**参考链接** 633 634[多态样式](../reference/apis-arkui/arkui-ts/ts-universal-attributes-polymorphic-style.md) 635 636## Scroll内Flex加宽高与滑动冲突(API 9) 637 638适用于Stage模型。 639 640**问题现象** 641 642当在Scroll组件中添加容器组件,并设置该容器组件的尺寸时,会破坏滚动布局。 643 644**解决措施** 645 646Scroll组件中的容器组件不设置尺寸,大小由内容撑开。 647 648 649## 父组件中如何处理子组件内点击事件(API 9) 650 651适用于Stage模型。 652 653在父组件中初始化子组件时,将父组件中定义的方法,传递给子组件,在子组件中调用该方法,类似于变量传递。 654 655**代码示例** 656 657``` 658class Model { 659 value: string = ""; 660} 661 662@Entry 663@Component 664struct EntryComponent { 665 test() { 666 console.log('testTag test in my component'); 667 } 668 669 build() { 670 Column() { 671 MyComponent({ title: { value: 'Hello World 2' }, count: 7, click: this.test }) //初始化时传递定义的方法 672 } 673 } 674} 675 676@Component 677struct MyComponent { 678 @State title: Model = { value: 'Hello World' }; 679 @State count: number = 0; 680 click: () => void = () => { 681 }; 682 private increaseBy: number = 1; 683 684 build() { 685 Column() { 686 Text(`${this.title.value}`).fontSize(30) 687 Button(`Click to increase count=${this.count}`) 688 .margin(20) 689 .onClick(() => { 690 // 修改内部状态变量count 691 this.count += this.increaseBy; 692 this.click(); 693 }) 694 } 695 } 696} 697``` 698 699 700## 如何主动拉起软键盘(API 9) 701 702**解决措施** 703 704可以通过focusControl.requestFocus控制输入框获焦,组件获焦后会自动弹起软键盘 705 706**参考链接** 707 708焦点控制:[焦点控制](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md) 709 710 711## SideBarContainer如何设置controlButton属性(API 9) 712 713**解决措施** 714 715示例代码: 716 717``` 718@Entry 719@Component 720struct SideBarContainerExample { 721 normalIcon: Resource = $r("app.media.icon") 722 selectedIcon: Resource = $r("app.media.icon") 723 @State arr: number[] = [1, 2, 3] 724 @State current: number = 1 725 726 build() { 727 SideBarContainer(SideBarContainerType.Embed) { 728 Column() { 729 ForEach(this.arr, (item, index) => { 730 Column({ space: 5 }) { 731 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 732 Text("Index0" + item) 733 .fontSize(25) 734 .fontColor(this.current === item ? '#0A59F7' : '#999') 735 .fontFamily('source-sans-pro,cursive,sans-serif') 736 } 737 .onClick(() => { 738 this.current = item 739 }) 740 }, item => item) 741 }.width('100%') 742 .justifyContent(FlexAlign.SpaceEvenly) 743 .backgroundColor('#19000000') 744 745 746 Column() { 747 Text('SideBarContainer content text1').fontSize(25) 748 Text('SideBarContainer content text2').fontSize(25) 749 } 750 .margin({ top: 50, left: 20, right: 30 }) 751 } 752 .sideBarWidth(150) 753 .minSideBarWidth(50) 754 .controlButton({ 755 left: 32, 756 top: 32, 757 width: 32, 758 height: 32, 759 icons: { shown: $r("app.media.icon"), 760 hidden: $r("app.media.icon"), 761 switching: $r("app.media.icon") } 762 }) 763 .maxSideBarWidth(300) 764 .onChange((value: boolean) => { 765 console.info('status:' + value) 766 }) 767 } 768} 769``` 770 771## 如何实现主动控制组件刷新(API 10) 772 773**解决措施** 774 775Canvas组件最终的显示内容分两种,一种是组件通用属性的绘制内容,比如背景色,boarder等这类组件属性方法设置的渲染属性,这类属性是可以通过状态变量驱动更新的。 776另一种是通过CanvasRenderingContext2D绘制接口由应用自行绘制的内容。该类命令时绘制接口不响应状态变量,该类接口内置表脏功能,只要调用就会在下一帧刷新绘制内容,不需要开发者显式刷新。 777 778**参考链接** 779 780[CanvasRenderingContext2D](../reference/apis-arkui/arkui-ts/ts-canvasrenderingcontext2d.md) 781 782## 怎么解决列表组件List在不设置高度的情况下,会出现滑动不到底的问题(API 10) 783 784**原因分析** 785 786List没有设置高度时,如果子组件总高度大于List父组件的高度时,List会取List父组件高度。如果List有其他兄弟节点,可能会吧List部分顶出父组件显示区域外,看起来像是划不到底部。 787 788**解决措施** 789 790List组件设置layoutWeight(1)属性,将剩余空间全部分配给List组件。 791 792**参考链接** 793 794[尺寸设置](../reference/apis-arkui/arkui-ts/ts-universal-attributes-size.md) 795 796## 如何实现瀑布流滑动时,数据的无限加载和显示(API 10) 797 798**解决措施** 799 8001.使用LazyForEach做瀑布流子节点。 801 8022.参考WaterFlow高性能开发指导在FlowItem的onAppear中判断是否即将触底,提前在LazyForEach数据源尾部新增数据;或在onScrollIndex11+事件中根据当前index进行判断。 803 804**参考链接** 805 806[WaterFlow高性能开发指导](../performance/waterflow_optimization.md) 807 808## customDialog中调用router.push启动新页面,会把customDialog关闭,怎么实现在不关闭弹窗的前提下启动新页面(API 10) 809 810**解决措施** 811 812开发者在路由跳转时,需要获取到主窗口的uiContext,再调用路由跳转。 813 814**参考链接** 815 816[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 817 818## 当前ArkUI-X的支持进展如何,有无明确路线图(API 10) 819 820**解决措施** 821 8221.进展:ArkUI-X当前已经开源,首版本已于2023-12-15正式发布,当前支持Android、iOS跨平台;另外,也在探索和试验桌面平台与Web平台的支持。 823 8242.[路线图](https://gitee.com/arkui-x/docs/blob/master/zh-cn/roadmap/ArkUI-X-roadmap-2023.md)。 825 826**参考链接** 827 828[ArkUI-X](https://gitee.com/arkui-x) 829 830## 应用如何在自定义组件的构建流程里跟踪组件数据或者状态(API 10) 831 832**问题现象** 833 834UI的构建build方法内无法插入日志,导致应用无法感知UI绘制流程,不利于调试UI,定位UI问题。 835 836**解决措施** 837 838使用@Watch回调来监测状态变量的变化,如果执行回调函数,说明在下一次vysnc信号发送时,使用该状态变量的UI会刷新绘制。 839 840示例代码如下: 841 842```ts 843@Prop @Watch('onCountUpdated') count: number = 0; 844@State total: number = 0; 845// @Watch 回调 846onCountUpdated(propName: string): void { 847 this.total += this.count; 848} 849``` 850 851**参考链接** 852 853[@Watch装饰器:状态变量更改通知](../ui/state-management/arkts-watch.md) 854 855## 自定义component不支持继承语法,针对其他框架支持的自定义组件继承及封装能力,ArkUI的解决方案是什么(API 10) 856 857**解决措施** 858 859对于声明式的自定义组件场景,不会提供继承的能力,需要使用组合的方式进行扩展,并结合后续提供的Modifier机制进行对现有组件属性的继承、复用和传递。 860 861## 组件支持的参数类型及参数单位类型区别是什么,使用场景是什么(API 10) 862 863**解决措施** 864 865屏幕像素单位px(pixel),表示屏幕上的实际像素,1px代表设备屏幕上的一个像素点。视窗逻辑像素单位lpx,lpx单位为实际屏幕宽度与逻辑宽度(通过designWidth配置)的比值,标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小。距离使用vp(virtual pixel),字体大小使用fp(font pixel),虚拟像素单位vp(virtual pixel),vp具体计算公式为:vp= px/(DPI/160)。 866以屏幕相对像素为单位, 是一台设备针对应用而言所具有的虚拟尺寸(区别于屏幕硬件本身的像素单位)。它提供了一种灵活的方式来适应不同屏幕密度的显示效果,使用虚拟像素,使元素在不同密度的设备上具有一致的视觉体量。字体像素单位fp(font pixel),字体像素(font pixel)大小默认情况下与vp相同,即默认情况下1fp=1vp。如果用户在设置中选择了更大的字体,字体的实际显示大小就会在vp的基础上乘以scale系数,即1fp=1vp*scale。Percentage - 需要指定以%像素单位,如'10%'。 867Resource - 资源引用类型,引入系统资源或者应用资源中的尺寸。 868 869## Surface模式下的XComponent组件在设置RenderFit后如果出现显示异常,该如何调整获取正确的显示效果(API 10) 870 871**解决措施** 872 873当Surface模式下的XComponent组件其内容与组件尺寸不一致时,可通过设置[renderFit](../reference/apis-arkui/arkui-ts/ts-universal-attributes-renderfit.md#renderfit18)属性,以调整绘制内容在组件尺寸范围内的布局方式,例如拉伸、居中、等比缩放等。 874在API version 18之前,Surface模式下的XComponent组件的[renderFit](../reference/apis-arkui/arkui-ts/ts-universal-attributes-renderfit.md#renderfit18)属性仅支持设置为RenderFit.RESIZE_FILL;如果设置为其他属性值可能会在部分机型出现显示异常。如果确实需要设置RESIZE_FILL之外的属性值,可以通过升级至API version 18或在XComponent组件的id字段中包含"RenderFitSurface"关键字来修正显示效果(在API version 18前)。 875 876示例代码如下: 877 878```ts 879// xxx.ets 880@Entry 881@Component 882struct Index { 883 @State xc_width: number = 500; 884 @State xc_height: number = 700; 885 myXComponentController: XComponentController = new XComponentController(); 886 887 build() { 888 Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) { 889 XComponent({ 890 id: 'myXComponent_RenderFitSurface', // 当id的字符串中包含"RenderFitSurface"时,可以使RenderFit显示正确。 891 type: XComponentType.SURFACE, 892 controller: this.myXComponentController 893 }) 894 .width(this.xc_width) 895 .height(this.xc_height) 896 .renderFit(RenderFit.CENTER) 897 } 898 .width('100%') 899 .height('100%') 900 } 901} 902 903```