1# ArkUI组件开发常见问题(ArkTS) 2 3## 自定义弹窗能否在ts文件中定义和使用 4 5适用于:OpenHarmony 3.2 Beta5 API 9 6 7自定义弹窗的定义和初始化需要用到属于ArkTS语法内容,必须在ets后缀文件中定义使用,不能在ts后缀文件中定义使用。 8 9**参考链接** 10 11[自定义弹窗](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 12 13## 自定义弹窗中的变量如何传递给页面 14 15适用于:OpenHarmony 3.2 Beta5 API 9 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 ``` 72 @CustomDialog 73 struct CustomDialog02 { 74 private inputValue: string 75 changeInputValue: (val: string) => void 76 controller: CustomDialogController 77 build() { 78 Column() { 79 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 80 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 81 .onChange((value: string) => { 82 this.changeInputValue(value) 83 }) 84 } 85 } 86 } 87 88 @Entry 89 @Component 90 struct DialogDemo02 { 91 @State inputValue: string = 'click me' 92 dialogController: CustomDialogController = new CustomDialogController({ 93 builder: CustomDialog02({ 94 inputValue: this.inputValue, 95 changeInputValue: (val: string) => { 96 this.inputValue = val 97 } 98 }) 99 }) 100 101 build() { 102 Column() { 103 Button(this.inputValue) 104 .onClick(() => { 105 this.dialogController.open() 106 }).backgroundColor(0x317aff) 107 }.width('100%').margin({ top: 5 }) 108 } 109 } 110 111 ``` 112 113- 方式三: 114 115 ``` 116 let storage = LocalStorage.GetShared() 117 @CustomDialog 118 struct CustomDialog03 { 119 @LocalStorageLink('inputVal') inputValue: string = '' 120 controller: CustomDialogController 121 build() { 122 Column() { 123 Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 }) 124 TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%') 125 .onChange((value: string) => { 126 this.inputValue = value; 127 }) 128 } 129 } 130 } 131 132 @Entry(storage) 133 @Component 134 struct DialogDemo03 { 135 @LocalStorageLink('inputVal') inputValue: string = '' 136 dialogController: CustomDialogController = new CustomDialogController({ 137 builder: CustomDialog03() 138 }) 139 140 build() { 141 Column() { 142 Button(this.inputValue) 143 .onClick(() => { 144 this.dialogController.open() 145 }).backgroundColor(0x317aff) 146 }.width('100%').margin({ top: 5 }) 147 } 148 } 149 150 ``` 151 152 153## 如何获取组件的宽高 154 155适用于:OpenHarmony 3.2 Beta5 API 9 156 157**问题现象** 158 159组件的宽高信息用于计算布局区域大小以及偏移量等内容,如何获取宽高信息? 160 161**解决措施** 162 163- 方式一:使用组件区域变化事件onAreaChange,在组件初始化或组件尺寸发生变化时触发。 164- 方式二:在点击或触摸事件中,事件的回调信息中存在目标元素的区域信息。 165 166**参考链接** 167 168[组件区域变化事件](../reference/arkui-ts/ts-universal-component-area-change-event.md),[点击事件](../reference/arkui-ts/ts-universal-events-click.md),[触摸事件](../reference/arkui-ts/ts-universal-events-touch.md) 169 170## 如何一键清空TextInput、TextArea组件内容 171 172适用于:OpenHarmony 3.2 Beta5 API 9 173 174**问题现象** 175 176TextInput,TextArea组件输入多字符后,需要实现点击清空。 177 178**解决措施** 179 180将状态变量赋值给TextInput或TextArea组件的text属性,在做点击清空事件时为状态变量赋值空字符串。 181 182**代码示例** 183 184``` 185struct Index { 186@State text: string = 'Hello World' 187controller: TextInputController = new TextInputController() 188 build() { 189 Row() { 190 Column() { 191 TextInput({ placeholder: 'Please input your words.', text: this.text, 192 controller:this.controller}).onChange((value) => { 193 this.text = value 194 }) 195 Button("Clear TextInput").onClick(() => { 196 this.text = ""; 197 }) 198 } 199 .width('100%') 200 } 201 .height('100%') 202 } 203} 204``` 205 206## 如何设置自定义弹窗位置 207 208适用于:OpenHarmony 3.2 Beta5 API 9 209 210**问题现象** 211 212自定义弹窗当前默认在窗口居中显示,当自定义弹窗需要与窗口边框对齐是需要设置自定义弹窗的对齐方式。 213 214**解决措施** 215 216初始化自定义弹窗时,通过alignment参数设置对齐方式,通过offset设置弹窗偏移量。 217 218**参考链接** 219 220[自定义弹窗](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 221 222## 如何隐藏容器组件的溢出内容 223 224适用于:OpenHarmony 3.2 Beta5 API 9 225 226**问题现象** 227 228当容器组件内容溢出时,表现为子组件边缘超出容器组件,需要进行隐藏设置。 229 230**解决措施** 231 232将通用属性-形状裁剪clip属性设置为true,表示按照容器边缘轮廓进行裁剪。此属性默认为false,表示不进行裁剪隐藏。 233 234**参考链接** 235 236[形状裁剪](../reference/arkui-ts/ts-universal-attributes-sharp-clipping.md) 237 238## 自定义弹窗大小如何自适应内容 239 240适用于:OpenHarmony 3.2 Beta5 API 9 241 242**问题现象** 243 244当自定义弹窗中存在可变化区域大小的子组件时,弹窗大小需要跟随自适应。 245 246**解决措施** 247 248- 方式一:采用弹窗容器默认样式。在默认样式中,弹窗容器高度自适应子节点,最大可为窗口高度的90%;弹窗容器的宽度根据栅格系统自适应,不跟随子节点变化。 249- 方式二:当显示设置customStyle为true时,弹窗宽高跟随子节点内容适应。 250 251**参考链接** 252 253[自定义弹窗](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 254 255## 如何理解自定义弹窗中的gridCount参数 256 257适用于:OpenHarmony 3.2 Beta5 API 9 258 259gridCount参数是指弹窗宽度占栅格列数的个数。系统把窗口宽等分,等分的份数即为栅格列数,不同设备栅格列数不同。假设设备屏幕密度值在320vp<=水平宽度<600vp,所以栅格列数是4,则gridCount的有效值在\[1, 4\]。 260 261注意:仅采用弹窗默认样式时设置有效。 262 263**参考链接** 264 265[自定义弹窗](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 266 267## 如何去除自定义弹窗的白色背景 268 269适用于:OpenHarmony 3.2 Beta5 API 9 270 271**问题现象** 272 273使用自定义弹窗时,默认样式中存在白色背景。 274 275**解决措施** 276 277需要采用自定义样式来消除自定义弹窗的白色背景: 278 2791. 在初始化自定义弹窗时设置customStyle为true。 2802. 在定义弹窗时设置组件背景色backgroundColor。 281 282**参考链接** 283 284[自定义弹窗](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 285 286## TextInput组件密码模式下,右边的眼睛图标能否支持自定义 287 288适用于:OpenHarmony 3.2 Beta5 API 9 289 290**问题现象** 291 292TextInput组件设置type为InputType.Password时,右侧出现眼睛图标,不能修改图标样式。 293 294**解决措施** 295 296当前图标不支持自定义,可使用TextInput的showPasswordIcon属性隐藏图标,使用Image组件替代控制TextInput组件的type。 297 298**参考链接** 299 300[TextInput组件](../reference/arkui-ts/ts-basic-components-textinput.md) 301 302## TextInput的onSubmit事件如何使用 303 304适用于:OpenHarmony 3.2 Beta5 API 9 305 306**问题现象** 307 308TextInput的onSubmit事件怎么触发,以及事件回调的参数类型代表的含义。 309 310**解决措施** 311 312onSubmit事件在外接键盘或软键盘回车时触发该回调,回调的参数为当前软键盘回车键类型。通过TextInput的enterKeyType属性可以设置输入法回车键类型,软键盘回车键样式需要输入法的支持。 313 314**参考链接** 315 316[TextInput组件](../reference/arkui-ts/ts-basic-components-textinput.md) 317 318## TextInput在聚焦时如何使光标回到起点 319 320适用于:OpenHarmony 3.2 Beta5 API 9 321 322**问题现象** 323 324TextInput组件在聚焦时,光标位置会自动根据触摸点位置变化,如何使得聚焦时光标固定显示在起点位置? 325 326**解决措施** 327 3281. TextInput组件绑定onEditChange事件,该事件TextInput可进行输入时触发。 3292. 在事件回调用TextInputController.caretPosition方法设置光标位置,不过需要用到setTimeout延迟方法。 330 331**代码示例** 332 333``` 334@Entry 335@Component 336struct TextInputDemo { 337 controller: TextInputController = new TextInputController() 338 339 build() { 340 Column() { 341 TextInput({ controller: this.controller }) 342 .onEditChange((isEditing: boolean) => { 343 if (isEditing) { 344 setTimeout(() => { 345 this.controller.caretPosition(0) 346 }, 100) 347 } 348 }) 349 } 350 } 351} 352``` 353 354**参考链接** 355 356[TextInput组件](../reference/arkui-ts/ts-basic-components-textinput.md) 357 358 359## 如何获取可滚动组件的当前滚动偏移量 360 361适用于:OpenHarmony 3.2 Beta5 API 9 362 363**问题现象** 364 365可滚动组件包含List,Grid,Scroll等,在发生滚动时如何获取滚动偏移量? 366 367**解决措施** 368 3691. 可滚动组件在初始化时可设置scroller参数,绑定滚动控制器。 3702. 通过控制器的currentOffset方法可获取水平和竖直方向的滚动偏移量。 371 372**参考链接** 373 374[Scroll](../reference/arkui-ts/ts-container-scroll.md#currentoffset) 375 376## 如何实现文本竖向排列 377 378适用于:OpenHarmony 3.2 Beta5 API 9 379 380**问题现象** 381 382使用Text组件时,无法将文本排列方向设置为竖向排列。 383 384**解决措施** 385 386Text组件当前文本排列方向固定为横向排列,要设置为竖向排列,可将文件拆分,使用Flex容器组件装填,设置主轴方向为竖向。 387 388**代码示例** 389 390``` 391@Entry 392@Component 393struct Index15 { 394 private message: string = '本文档适用于应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉应用开发流程。'; 395 build() { 396 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 397 ForEach(this.message.split(''), (item, index) => { 398 Text(item) 399 .fontSize(30) 400 .flexShrink(0) 401 }) 402 } 403 } 404} 405``` 406 407## 如何将Ability的UI界面设置成透明 408 409适用于:OpenHarmony 3.2 Beta5,API9 410 411**问题现象** 412 413如何设置Ability的UI界面为透明 414 415**解决措施** 416 417将最上层容器组件背景色设置为透明,然后通过设置XComponent组件的opacity属性值为0.01来实现。 418 419示例: 420 421``` 422build() { 423 Stack() { 424 XComponent({ 425 id: 'componentId', 426 type: 'surface', 427 }) 428 .width('100%') 429 .height('100%') 430 .opacity(0.01) 431 // 页面内容 432 } 433 .width('100%') 434 .height('100%') 435 .backgroundColor('rgba(255,255,255, 0)') 436} 437``` 438 439## constraintSize尺寸设置不生效 440 441适用于:Openharmony 3.2 Beta5 API 9 stage模型 442 443**问题现象** 444 445constraintSize约束组件尺寸时,子组件内设置百分比宽度,例如width\('100%'\)会采用constraintSize约束中的最大宽乘百分比,导致撑开组件,看起来constraintSize设置没生效。 446 447**解决措施** 448 449可以在外层使用Scroll组件,设置constraintSize,当子组件占用空间超过设置的约束值时,会显示滚动条。 450 451## 如何将背景颜色设置为透明 452 453适用于:OpenHarmony 3.2 Beta5 API 9 454 455**解决措施** 456 457将backgroundColor设置为 '\#00000000'。 458 459## Scroll组件滚动到达不了最底部 460 461适用于:OpenHarmony 3.2 Beta5 API 9 Stage模型 462 463**问题现象** 464 465Scroll组件在未设置高度情况下,默认为窗口高度,当滚动区域外存在其他组件时,滚动底部区域会出现遮挡。 466 467**解决措施** 468 469Scroll组件需要设置Scroll高度,或者使用Flex布局限制Scroll高度。 470 471## 如何自定义Video组件控制栏样式 472 473适用于:OpenHarmony 3.2 Beta5 API 9 Stage模型 474 475**解决措施** 476 4771. 通过设置属性controls为false关闭默认控制栏。 478 4792. 设置Video组件的controller。 480 4813. 通过ArkTS实现自定义的控制栏,并通过VideoController控制视频播放。 482 483**代码示例** 484 485``` 486// xxx.ets 487@Entry@Componentstruct VideoCreateComponent { 488 @State videoSrc: Resource = $rawfile('video1.mp4') 489 @State previewUri: Resource = $r('app.media.poster1') 490 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 491 @State isAutoPlay: boolean = false 492 @State showControls: boolean = true 493 controller: VideoController = new VideoController() 494 build() { 495 Column() { 496 Video({ 497 src: this.videoSrc, 498 previewUri: this.previewUri, 499 currentProgressRate: this.curRate, 500 controller: this.controller 501 }).width('100%').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 Row() { 541 Button('start').onClick(() => { 542 this.controller.start() // 开始播放 543 }).margin(5) 544 Button('pause').onClick(() => { 545 this.controller.pause() // 暂停播放 546 }).margin(5) 547 Button('stop').onClick(() => { 548 this.controller.stop() // 结束播放 549 }).margin(5) 550 Button('setTime').onClick(() => { 551 this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置 552 }).margin(5) 553 } 554 Row() { 555 Button('rate 0.75').onClick(() => { 556 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放 557 }).margin(5) 558 Button('rate 1').onClick(() => { 559 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放 560 }).margin(5) 561 Button('rate 2').onClick(() => { 562 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放 563 }).margin(5) 564 } 565 } 566 }} 567``` 568 569**参考链接** 570 571[Video](../reference/arkui-ts/ts-media-components-video.md#start) 572 573## 如何设置组件不同状态下的样式 574 575**问题现象** 576 577对应组件的不同状态(如无状态、按下、禁用、聚焦、点击),显示不同的样式。 578 579**解决措施** 580 581使用多态样式,在组件的StateStyles接口中,定义组件不同状态下的样式。 582 583**代码示例** 584 585``` 586//xxx.ts 587@Entry 588@Component 589struct StyleExample { 590 @State isEnable: boolean = true; 591 592 @Styles pressedStyles() { 593 .backgroundColor("#ED6F21") 594 .borderRadius(10) 595 .borderStyle(BorderStyle.Dashed) 596 .borderWidth(2) 597 .borderColor('#33000000') 598 .width(120) 599 .height(30) 600 .opacity(1) 601 } 602 build() { 603 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 604 Text("pressed") 605 .backgroundColor('#0A59F7') 606 .borderRadius(20) 607 .borderStyle(BorderStyle.Dotted) 608 .borderWidth(2) 609 .borderColor(Color.Red) 610 .width(100) 611 .height(25) 612 .opacity(1) 613 .fontSize(14) 614 .fontColor(Color.White) 615 .stateStyles({ 616 pressed: this.pressedStyles 617 }) 618 .margin({ 619 bottom: 20 620 }) 621 .textAlign(TextAlign.Center) 622 } 623 .width(350) 624 .height(300) 625 } 626} 627``` 628 629**参考链接** 630 631[多态样式](../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md) 632 633## Scroll内Flex加宽高与滑动冲突 634 635适用于:OpenHarmony 3.2 Beta5 API 9 Stage模型 636 637**问题现象** 638 639当在Scroll组件中添加容器组件,并设置该容器组件的尺寸时,会破坏滚动布局。 640 641**解决措施** 642 643Scroll组件中的容器组件不设置尺寸,大小由内容撑开。 644 645## 父组件中如何处理子组件内点击事件 646 647适用于:OpenHarmony 3.2 Beta5 API 9 Stage模型 648 649在父组件中初始化子组件时,将父组件中定义的方法,传递给子组件,在子组件中调用该方法,类似于变量传递。 650 651**代码示例** 652 653``` 654class Model { 655 value: string 656} 657@Entry 658@Component 659struct EntryComponent { 660 test() { 661 console.log('testTag test in my component'); 662 } 663 build() { 664 Column() { 665 MyComponent({ title: { value: 'Hello World 2' }, count: 7, onClick: this.test }) //初始化时传递定义的方法 666 } 667 } 668} 669 670@Component 671struct MyComponent { 672 @State title: Model = { value: 'Hello World' } 673 @State count: number = 0 674 onClick: any; 675 private toggle: string = 'Hello World' 676 private increaseBy: number = 1 677 678 build() { 679 Column() { 680 Text(`${this.title.value}`).fontSize(30) 681 Button(`Click to increase count=${this.count}`) 682 .margin(20) 683 .onClick(() => { 684 // 修改内部状态变量count 685 this.count += this.increaseBy 686 this.onClick.call(); 687 }) 688 } 689 } 690} 691``` 692 693## 如何主动拉起软键盘 694 695适用于OpenHarmony 3.2 Beta5 API 9 696 697**解决措施** 698 699可以通过focusControl.requestFocus控制输入框获焦,组件获焦后会自动弹起软键盘 700 701**参考链接** 702 703焦点控制:[焦点控制](../reference/arkui-ts/ts-universal-attributes-focus.md) 704 705## SideBarContainer如何设置controlButton属性 706 707适用于 OpenHarmony 3.2 Beta5,API9 708 709**解决措施** 710 711示例代码: 712 713``` 714@Entry 715@Component 716struct SideBarContainerExample { 717 normalIcon : Resource = $r("app.media.icon") 718 selectedIcon: Resource = $r("app.media.icon") 719 @State arr: number[] = [1, 2, 3] 720 @State current: number = 1 721 722 build() { 723 SideBarContainer(SideBarContainerType.Embed) 724 { 725 Column() { 726 ForEach(this.arr, (item, index) => { 727 Column({ space: 5 }) { 728 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 729 Text("Index0" + item) 730 .fontSize(25) 731 .fontColor(this.current === item ? '#0A59F7' : '#999') 732 .fontFamily('source-sans-pro,cursive,sans-serif') 733 } 734 .onClick(() => { 735 this.current = item 736 }) 737 }, item => item) 738 }.width('100%') 739 .justifyContent(FlexAlign.SpaceEvenly) 740 .backgroundColor('#19000000') 741 742 743 Column() { 744 Text('SideBarContainer content text1').fontSize(25) 745 Text('SideBarContainer content text2').fontSize(25) 746 } 747 .margin({ top: 50, left: 20, right: 30 }) 748 } 749 .sideBarWidth(150) 750 .minSideBarWidth(50) 751 .controlButton({left:32, 752 top:32, 753 width:32, 754 height:32, 755 icons:{shown: $r("app.media.icon"), 756 hidden: $r("app.media.icon"), 757 switching: $r("app.media.icon")}}) 758 .maxSideBarWidth(300) 759 .onChange((value: boolean) => { 760 console.info('status:' + value) 761 }) 762 } 763} 764``` 765