1# ArkUI Component Development (ArkTS) 2 3## Can custom dialog boxes be defined and used in .ts files? 4 5Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 6 7Unfortunately not. Custom dialog boxes require ArkTS syntax for definition and initialization. Therefore, they can be defined and used only in .ets files. 8 9**Reference** 10 11[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 12 13## How do I transfer variables in a custom dialog box to a page? 14 15Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 16 17**Symptom** 18 19The variable defined in a custom dialog box needs to be transferred to the page when the dialog box is closed or the variable changes. 20 21**Solution** 22 23- Method 1: Define the variable as a state variable of the custom dialog box. 24- Method 2: During initialization of the custom dialog box, pass to it a method, which is triggered in the custom dialog box and accepts the variable in the custom dialog box as a parameter. 25- Method 3: Use AppStorage or LocalStorage to manage page state and implement state sharing between the custom dialog box and page. 26 27**Example** 28 29- Method 1: 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- Method 2: 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- Method 3: 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## How do I obtain the width and height of a component? 154 155Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 156 157**Symptom** 158 159The width and height of a component need to be obtained to calculate the size and offset of the layout area. 160 161**Solution** 162 163- Method 1: Use the **onAreaChange** event of the component, which is triggered when the component is initialized or the component size changes. 164- Manner 2: Use the callback in the click or touch event, which provides the area information of the target element. 165 166**Reference** 167 168[Component Area Change Event](../reference/arkui-ts/ts-universal-component-area-change-event.md), [Click Event](../reference/arkui-ts/ts-universal-events-click.md), [Touch Event](../reference/arkui-ts/ts-universal-events-touch.md) 169 170## How do I clear the content of the \<TextInput> and \<TextArea> components by one click? 171 172Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 173 174**Symptom** 175 176A click-to-clear feature is required to remove all characters in the **\<TextInput>** and **\<TextArea>** component at once. 177 178**Solution** 179 180Convert the **text** attribute of the **\<TextInput>** and **\<TextArea>** component to a state variable. Assign an empty string to the state variable when the click-to-clear event is performed. 181 182**Example** 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## How do I set the position of a custom dialog box? 207 208Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 209 210**Symptom** 211 212By default, a custom dialog box is displayed in the center of the window. In some cases, it needs to be aligned with the window border. 213 214**Solution** 215 216During initialization of the custom dialog box, set the **alignment** and **offset** parameters. 217 218**Reference** 219 220[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 221 222## How do I hide the overflow content of a container component? 223 224Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 225 226**Symptom** 227 228When content overflows in a container component, that is, the child component does not fit in the container component, the overflow content needs to be processed. 229 230**Solution** 231 232To clip and hide overflow content, set the **clip** universal attribute to **true**. By default, this attribute is set to **false**. 233 234**Reference** 235 236[Shape Clipping](../reference/arkui-ts/ts-universal-attributes-sharp-clipping.md) 237 238## How do I set a custom dialog box to automatically adapt its size to content? 239 240Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 241 242**Symptom** 243 244When a custom dialog box contains a child component whose area size can be changed, it needs to automatically adjust its size. 245 246**Solution** 247 248- Method 1: Set the custom dialog box to the default style. In this style, the dialog box automatically adapts its width to the grid system and its height to the child components; the maximum height is 90% of the container height. 249- Method 2: Set the custom dialog box to a custom style. In this style, the dialog box automatically adapts its width and height to the child components. 250 251**Reference** 252 253[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 254 255## What is the function of the gridCount parameter in the custom dialog box? 256 257Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 258 259The **gridCount** parameter indicates the number of grid columns occupied by the dialog box. The system divides the window width into equal regions. The number of equal regions is the number of grid columns, which varies by device. For example, if the screen density of a device is 320 vp <= horizontal width < 600 vp, the number of grid columns is 4, and the valid value of **gridCount** is \[1, 4\]. 260 261Note: This parameter is valid only when the custom dialog box is in the default style. 262 263**Reference** 264 265[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 266 267## How do I remove the white background of a custom dialog box? 268 269Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 270 271**Symptom** 272 273When in the default style a custom dialog box comes with a white background. 274 275**Solution** 276 277To remove the white background, set the custom dialog box to a custom style. 278 2791. During initialization of the custom dialog box, set **customStyle** to **true**. 2802. During initialization of the custom dialog box, set **backgroundColor** to the color you prefer. 281 282**Reference** 283 284[Custom Dialog Box](../reference/arkui-ts/ts-methods-custom-dialog-box.md) 285 286## How do I customize the eye icon for the password input mode of the \<TextInput> component? 287 288Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 289 290**Symptom** 291 292The eye icon for the password input mode (with the **type** attribute of the **\<TextInput>** component set to **InputType.Password**) cannot be customized. 293 294**Solution** 295 296The eye icon itself cannot be customized. You can use set the **showPasswordIcon** attribute of the **\<TextInput>** component to **false** to hide the icon, and use the **\<Image>** component to control the type of the **\<TextInput>** component. 297 298**Reference** 299 300[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 301 302## How do I use the onSubmit event of the \<TextInput> component? 303 304Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 305 306**Solution** 307 308The **onSubmit** event is triggered when a user presses **Enter** on the (physical or soft) keyboard. The callback parameter in the event is the current Enter key type. The Enter key type can be set through the **enterKeyType** attribute of the **\<TextInput>** component. Setting the key style of the soft keyboard requires support by the input method. 309 310**Reference** 311 312[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 313 314## How do I set the caret position to the start point for when the \<TextInput> component obtains focus? 315 316Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 317 318**Symptom** 319 320When the **\<TextInput>** component obtains focus, the caret automatically moves to the position of the touch point, instead of the start position. 321 322**Solution** 323 3241. Bind the **\<TextInput>** component to the **onEditChange** event, which is triggered when the component enters the input state. 3252. Call the **setTimeout** API for asynchronous processing. Then call the **TextInputController.caretPosition** API in the event callback to set the caret position. 326 327**Example** 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**Reference** 351 352[TextInput](../reference/arkui-ts/ts-basic-components-textinput.md) 353 354 355## How do I obtain the current scrolling offset of a scrollable component? 356 357Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 358 359**Solution** 360 3611. During initialization of the scrollable component, such as **\<List>**, **\<Grid>**, and **\<Scroll>**, set the **scroller** parameter to bind the component to a scroll controller. 3622. Call the **currentOffset** API of the controller to obtain the horizontal and vertical scrolling offsets. 363 364**Reference** 365 366[Scroll](../reference/arkui-ts/ts-container-scroll.md#currentoffset) 367 368## How do I align text vertically? 369 370Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 371 372**Symptom** 373 374Text cannot be aligned vertically in the **\<Text>** component. 375 376**Solution** 377 378Text is aligned horizontally in the **\<Text>** component. To enable text to align vertically, you can split the file, include it in a **\<Flex>** container, and set the container's main axis direction to vertical. 379 380**Example** 381 382``` 383@Entry 384@Component 385struct Index15 { 386 private message: string = 'This document is intended for novices in developing applications. It introduces you to the application development process and main files in the project director, by walking you through the building of a simple application with the page redirection/return feature.'; 387 build() { 388 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 389 ForEach(this.message.split(''), (item, index) => { 390 Text(item) 391 .fontSize(30) 392 .flexShrink(0) 393 }) 394 } 395 } 396} 397``` 398 399## How do I set the UI of an ability to transparent? 400 401Applicable to: OpenHarmony 3.2 Beta5 (API version 9) 402 403**Solution** 404 405Set the background color of the top container component to transparent, and then set the **opacity** attribute of the XComponent to **0.01**. 406 407**Example** 408 409``` 410build() { 411 Stack() { 412 XComponent({ 413 id: 'componentId', 414 type: 'surface', 415 }) 416 .width('100%') 417 .height('100%') 418 .opacity(0.01) 419 // Page content 420 } 421 .width('100%') 422 .height('100%') 423 .backgroundColor('rgba(255,255,255, 0)') 424} 425``` 426 427## Why do the constraintSize settings fail to take effect? 428 429Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 430 431**Symptom** 432 433If **constraintSize** is set for a component and the width of its child component is set to a percentage, for example, **width\('100%'\)**, **constraintSize** takes effect by multiplying the maximum width by the percentage. As a result, the child component may overflow, in which case it looks like the **constraintSize** settings fail to take effect. 434 435**Solution** 436 437You can use the **\<Scroll>** component at the outer layer. In this way, when **constraintSize** is set and the space occupied by a child component exceeds the specified constraint value, a scrollbar will be displayed. 438 439## How do I set the background color to transparent? 440 441Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 442 443**Solution** 444 445Set **backgroundColor** to **'\#00000000'**. 446 447## What should I do if the \<Scroll> component cannot scroll to the bottom? 448 449Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 450 451**Symptom** 452 453Unless otherwise specified, the height of the **\<Scroll>** component is equal to the window height. In this case, the component's bottom area will be blocked by components (if any) outside of it. 454 455**Solution** 456 457Set the height of the **\<Scroll>** component or use the flex layout to limit this height. 458 459## How do I customize the control bar style of the \<Video> component? 460 461Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 462 463**Solution** 464 4651. Set **controls** to **false** to disable the default control bar. 466 4672. Sets **controller** for the **\<Video>** component. 468 4693. Implement a custom control bar in ArkTS and use **VideoController** to control video playback. 470 471**Example** 472 473``` 474// xxx.ets 475@Entry@Componentstruct VideoCreateComponent { 476 @State videoSrc: Resource = $rawfile('video1.mp4') 477 @State previewUri: Resource = $r('app.media.poster1') 478 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 479 @State isAutoPlay: boolean = false 480 @State showControls: boolean = true 481 controller: VideoController = new VideoController() 482 build() { 483 Column() { 484 Video({ 485 src: this.videoSrc, 486 previewUri: this.previewUri, 487 currentProgressRate: this.curRate, 488 controller: this.controller 489 }).width('100%').height(600) 490 .autoPlay(this.isAutoPlay) 491 .controls(this.showControls) 492 .onStart(() => { 493 console.info('onStart') 494 }) 495 .onPause(() => { 496 console.info('onPause') 497 }) 498 .onFinish(() => { 499 console.info('onFinish') 500 }) 501 .onError(() => { 502 console.info('onError') 503 }) 504 .onPrepared((e) => { 505 console.info('onPrepared is ' + e.duration) 506 }) 507 .onSeeking((e) => { 508 console.info('onSeeking is ' + e.time) 509 }) 510 .onSeeked((e) => { 511 console.info('onSeeked is ' + e.time) 512 }) 513 .onUpdate((e) => { 514 console.info('onUpdate is ' + e.time) 515 }) 516 Row() { 517 Button('src').onClick(() => { 518 this.videoSrc = $rawfile('video2.mp4') // Switch the video source. 519 }).margin(5) 520 Button('previewUri').onClick(() => { 521 this.previewUri = $r('app.media.poster2') // Switch the preview image. 522 }).margin(5) 523 524 Button('controls').onClick(() => { 525 this.showControls =! this.showControls // Specify whether to show the control bar. 526 }).margin(5) 527 } 528 Row() { 529 Button('start').onClick(() => { 530 this.controller.start() // Start playback. 531 }).margin(5) 532 Button('pause').onClick(() => { 533 this.controller.pause() // Pause playback. 534 }).margin(5) 535 Button('stop').onClick(() => { 536 this.controller.stop() // Stop playback. 537 }).margin(5) 538 Button('setTime').onClick(() => { 539 this.controller.setCurrentTime(10, SeekMode.Accurate) // Seek to the 10s position of the video. 540 }).margin(5) 541 } 542 Row() { 543 Button('rate 0.75').onClick(() => { 544 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // Play the video at the 0.75x speed. 545 }).margin(5) 546 Button('rate 1').onClick(() => { 547 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // Play the video at the 1x speed. 548 }).margin(5) 549 Button('rate 2').onClick(() => { 550 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // Play the video at the 2x speed. 551 }).margin(5) 552 } 553 } 554 }} 555``` 556 557**Reference** 558 559[Video](../reference/arkui-ts/ts-media-components-video.md#start) 560 561## How do I set state-specific styles for a component? 562 563**Solution** 564 565You can use the **stateStyles** attribute to set styles of a component for different states (stateless, pressed, disabled, focused, or clicked). 566 567**Example** 568 569``` 570//xxx.ts 571@Entry 572@Component 573struct StyleExample { 574 @State isEnable: boolean = true; 575 576 @Styles pressedStyles() { 577 .backgroundColor("#ED6F21") 578 .borderRadius(10) 579 .borderStyle(BorderStyle.Dashed) 580 .borderWidth(2) 581 .borderColor('#33000000') 582 .width(120) 583 .height(30) 584 .opacity(1) 585 } 586 build() { 587 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 588 Text("pressed") 589 .backgroundColor('#0A59F7') 590 .borderRadius(20) 591 .borderStyle(BorderStyle.Dotted) 592 .borderWidth(2) 593 .borderColor(Color.Red) 594 .width(100) 595 .height(25) 596 .opacity(1) 597 .fontSize(14) 598 .fontColor(Color.White) 599 .stateStyles({ 600 pressed: this.pressedStyles 601 }) 602 .margin({ 603 bottom: 20 604 }) 605 .textAlign(TextAlign.Center) 606 } 607 .width(350) 608 .height(300) 609 } 610} 611``` 612 613**Reference** 614 615[Polymorphic Style](../reference/arkui-ts/ts-universal-attributes-polymorphic-style.md) 616 617## What should I do if the flex width and height in the \<Scroll> component conflicts with the scrolling? 618 619Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 620 621**Symptom** 622 623When a container component with a fixed size is added to the **\<Scroll>** component, a scrolling error occurs. 624 625**Solution** 626 627Do not set a size for any container component in the **\<Scroll>** component. In this way, the **\<Scroll>** component can adapt its size to the content. 628 629## How does a component process click events in its child components? 630 631Applicable to: OpenHarmony 3.2 Beta5 (API version 9, stage model) 632 633When a child component is initialized in the parent component, the method defined in the parent component is transferred to and invoked in the child component. This process is similar to variable transfer. 634 635**Example** 636 637``` 638class Model { 639 value: string 640} 641@Entry 642@Component 643struct EntryComponent { 644 test() { 645 console.log('testTag test in my component'); 646 } 647 build() { 648 Column() { 649 MyComponent({ title: { value: 'Hello World 2' }, count: 7, onClick: this.test }) // The defined method is transferred during initialization. 650 } 651 } 652} 653 654@Component 655struct MyComponent { 656 @State title: Model = { value: 'Hello World' } 657 @State count: number = 0 658 onClick: any; 659 private toggle: string = 'Hello World' 660 private increaseBy: number = 1 661 662 build() { 663 Column() { 664 Text(`${this.title.value}`).fontSize(30) 665 Button(`Click to increase count=${this.count}`) 666 .margin(20) 667 .onClick(() => { 668 // Change the count value of the internal state variable. 669 this.count += this.increaseBy 670 this.onClick.call(); 671 }) 672 } 673 } 674} 675``` 676 677## How do I implement a text input box that automatically brings up the soft keyboard? 678 679Applicable to: OpenHarmony 3.2 Beta 5 (API version 9) 680 681**Solution** 682 683You can use **focusControl.requestFocus** to control the focus of the text input box. When the text input box is in focus, it automatically brings up the soft keyboard. 684 685**Reference** 686 687[Focus Control](../reference/arkui-ts/ts-universal-attributes-focus.md) 688 689## How do I set the controlButton attribute for the \<SideBarContainer> component? 690 691Applicable to: OpenHarmony 3.2 Beta5 (API version 9) 692 693**Solution** 694 695Refer to the following sample code: 696 697``` 698@Entry 699@Component 700struct SideBarContainerExample { 701 normalIcon : Resource = $r("app.media.icon") 702 selectedIcon: Resource = $r("app.media.icon") 703 @State arr: number[] = [1, 2, 3] 704 @State current: number = 1 705 706 build() { 707 SideBarContainer(SideBarContainerType.Embed) 708 { 709 Column() { 710 ForEach(this.arr, (item, index) => { 711 Column({ space: 5 }) { 712 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 713 Text("Index0" + item) 714 .fontSize(25) 715 .fontColor(this.current === item ? '#0A59F7' : '#999') 716 .fontFamily('source-sans-pro,cursive,sans-serif') 717 } 718 .onClick(() => { 719 this.current = item 720 }) 721 }, item => item) 722 }.width('100%') 723 .justifyContent(FlexAlign.SpaceEvenly) 724 .backgroundColor('#19000000') 725 726 727 Column() { 728 Text('SideBarContainer content text1').fontSize(25) 729 Text('SideBarContainer content text2').fontSize(25) 730 } 731 .margin({ top: 50, left: 20, right: 30 }) 732 } 733 .sideBarWidth(150) 734 .minSideBarWidth(50) 735 .controlButton({left:32, 736 top:32, 737 width:32, 738 height:32, 739 icons:{shown: $r("app.media.icon"), 740 hidden: $r("app.media.icon"), 741 switching: $r("app.media.icon")}}) 742 .maxSideBarWidth(300) 743 .onChange((value: boolean) => { 744 console.info('status:' + value) 745 }) 746 } 747} 748``` 749