1# ArkUI Component Development (ArkTS) 2 3 4## Can custom dialog boxes be defined and used in .ts files? (API version 9) 5 6Unfortunately not. Custom dialog boxes require ArkTS syntax for definition and initialization. Therefore, they can be defined and used only in .ets files. 7 8**Reference** 9 10[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 11 12 13## How do I pass variables in a custom dialog box to a page? (API version 9) 14 15**Symptom** 16 17The variable defined in a custom dialog box needs to be transferred to the page when the dialog box is closed or the variable changes. 18 19**Solution** 20 21- Method 1: Define the variable as a state variable of the custom dialog box. 22 23- 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. 24 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- Method 2: 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- Method 3: 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## How do I obtain the width and height of a component? (API version 9) 151 152**Symptom** 153 154The width and height of a component need to be obtained to calculate the size and offset of the layout area. 155 156**Solution** 157 158- Method 1: Use the **onAreaChange** event of the component, which is triggered when the component is initialized or the component size changes. 159 160- Manner 2: Use the callback in the click or touch event, which provides the area information of the target element. 161 162**Reference** 163 164[Component Area Change Event](../reference/apis-arkui/arkui-ts/ts-universal-component-area-change-event.md), [Click Event](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md), [Touch Event](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) 165 166 167## How do I clear the content of the TextInput and TextArea components by one click? (API version 9) 168 169**Symptom** 170 171A click-to-clear feature is required to remove all characters in the **TextInput** and **TextArea** component at once. 172 173**Solution** 174 175Convert 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. 176 177**Example** 178 179``` 180struct Index { 181@State text: string = 'Hello World' 182controller: TextInputController = new TextInputController() 183 build() { 184 Row() { 185 Column() { 186 TextInput({ placeholder: 'Please input your words.', text: this.text, 187 controller:this.controller}).onChange((value) => { 188 this.text = value 189 }) 190 Button("Clear TextInput").onClick(() => { 191 this.text = ""; 192 }) 193 } 194 .width('100%') 195 } 196 .height('100%') 197 } 198} 199``` 200 201 202## How do I set the position of a custom dialog box? (API version 9) 203 204**Symptom** 205 206By 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. 207 208**Solution** 209 210During initialization of the custom dialog box, set the **alignment** and **offset** parameters. 211 212**Reference** 213 214[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 215 216 217## How do I hide the overflow content of a container component? (API version 9) 218 219**Symptom** 220 221When 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. 222 223**Solution** 224 225To clip and hide overflow content, set the **clip** universal attribute to **true**. By default, this attribute is set to **false**. 226 227**Reference** 228 229[Shape Clipping](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sharp-clipping.md) 230 231 232## How do I set a custom dialog box to automatically adapt its size to content? (API version 9) 233 234**Symptom** 235 236When a custom dialog box contains a child component whose area size can be changed, it needs to automatically adjust its size. 237 238**Solution** 239 240- 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. 241 242- 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. 243 244**Reference** 245 246[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 247 248 249## What is the gridCount parameter of the custom dialog box used for? (API version 9) 250 251The **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]. 252 253Note: This parameter is valid only when the custom dialog box is in the default style. 254 255**Reference** 256 257[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 258 259 260## How do I remove the white background of a custom dialog box? (API version 9) 261 262**Symptom** 263 264When in the default style a custom dialog box comes with a white background. 265 266**Solution** 267 268To remove the white background, set the custom dialog box to a custom style. 269 2701. During initialization of the custom dialog box, set **customStyle** to **true**. 271 2722. During initialization of the custom dialog box, set **backgroundColor** to the color you prefer. 273 274**Reference** 275 276[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 277 278 279## How do I customize the eye icon for the password input mode of the TextInput component? (API version 9) 280 281**Symptom** 282 283The eye icon for the password input mode (with the **type** attribute of the **TextInput** component set to **InputType.Password**) cannot be customized. 284 285**Solution** 286 287The 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. 288 289**Reference** 290 291[TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 292 293 294## How do I use the onSubmit event of the TextInput component? (API version 9) 295 296**Solution** 297 298The **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. 299 300**Reference** 301 302[TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 303 304 305## How do I set the caret position to the start point for when the TextInput component obtains focus? (API version 9) 306 307**Symptom** 308 309When the **TextInput** component obtains focus, the caret automatically moves to the position of the touch point, instead of the start position. 310 311**Solution** 312 3131. Bind the **TextInput** component to the **onEditChange** event, which is triggered when the component enters the input state. 314 3152. Call the **setTimeout** API for asynchronous processing. Then call the **TextInputController.caretPosition** API in the event callback to set the caret position. 316 317**Example** 318 319``` 320@Entry 321@Component 322struct TextInputDemo { 323 controller: TextInputController = new TextInputController() 324 325 build() { 326 Column() { 327 TextInput({ controller: this.controller }) 328 .onEditChange((isEditing: boolean) => { 329 if (isEditing) { 330 setTimeout(() => { 331 this.controller.caretPosition(0) 332 }, 100) 333 } 334 }) 335 } 336 } 337} 338``` 339 340**Reference** 341 342[TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) 343 344 345## How do I obtain the current scrolling offset of a scrollable component? (API version 9) 346 347**Solution** 348 3491. During initialization of the scrollable component, such as **List**, **Grid**, and **Scroll**, set the **scroller** parameter to bind the component to a scroll controller. 350 3512. Call the **currentOffset** API of the controller to obtain the horizontal and vertical scrolling offsets. 352 353**Reference** 354 355[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#currentoffset) 356 357 358## How do I align text vertically? (API version 9) 359 360**Symptom** 361 362Text cannot be aligned vertically in the **Text** component. 363 364**Solution** 365 366Text 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. 367 368**Example** 369 370``` 371@Entry 372@Component 373struct Index15 { 374 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.'; 375 build() { 376 Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) { 377 ForEach(this.message.split(''), (item, index) => { 378 Text(item) 379 .fontSize(30) 380 .flexShrink(0) 381 }) 382 } 383 } 384} 385``` 386 387 388## How do I set the UI of an ability to transparent? (API version 9) 389 390**Solution** 391 392Set the background color of the top container component to transparent, and then set the **opacity** attribute of the XComponent to **0.01**. 393 394**Example** 395 396``` 397build() { 398 Stack() { 399 XComponent({ 400 id: 'componentId', 401 type: 'surface', 402 }) 403 .width('100%') 404 .height('100%') 405 .opacity(0.01) 406 // Page content 407 } 408 .width('100%') 409 .height('100%') 410 .backgroundColor('rgba(255,255,255, 0)') 411} 412``` 413 414 415## Why do the constraintSize settings fail to take effect? (API version 9) 416 417Applicable to: stage model 418 419**Symptom** 420 421If **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. 422 423**Solution** 424 425You 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. 426 427 428## How do I set the background color to transparent? (API version 9) 429 430**Solution** 431 432Set **backgroundColor** to **'\#00000000'**. 433 434 435## What should I do if the Scroll component cannot scroll to the bottom? (API version 9) 436 437Applicable to: stage model 438 439**Symptom** 440 441Unless 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. 442 443**Solution** 444 445Set the height of the **Scroll** component or use the flex layout to limit this height. 446 447 448## How do I customize the control bar style of the Video component? (API version 9) 449 450Applicable to: stage model 451 452**Solution** 453 4541. Set **controls** to **false** to disable the default control bar. 455 4562. Set **controller** for the **Video** component. 457 4583. Implement a custom control bar in ArkTS and use **VideoController** to control video playback. 459 460**Example** 461 462``` 463// xxx.ets 464@Entry@Componentstruct VideoCreateComponent { 465 @State videoSrc: Resource = $rawfile('video1.mp4') 466 @State previewUri: Resource = $r('app.media.poster1') 467 @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X 468 @State isAutoPlay: boolean = false 469 @State showControls: boolean = true 470 controller: VideoController = new VideoController() 471 build() { 472 Column() { 473 Video({ 474 src: this.videoSrc, 475 previewUri: this.previewUri, 476 currentProgressRate: this.curRate, 477 controller: this.controller 478 }).width('100%').height(600) 479 .autoPlay(this.isAutoPlay) 480 .controls(this.showControls) 481 .onStart(() => { 482 console.info('onStart') 483 }) 484 .onPause(() => { 485 console.info('onPause') 486 }) 487 .onFinish(() => { 488 console.info('onFinish') 489 }) 490 .onError(() => { 491 console.info('onError') 492 }) 493 .onPrepared((e) => { 494 console.info('onPrepared is ' + e.duration) 495 }) 496 .onSeeking((e) => { 497 console.info('onSeeking is ' + e.time) 498 }) 499 .onSeeked((e) => { 500 console.info('onSeeked is ' + e.time) 501 }) 502 .onUpdate((e) => { 503 console.info('onUpdate is ' + e.time) 504 }) 505 Row() { 506 Button('src').onClick(() => { 507 this.videoSrc = $rawfile('video2.mp4') // Switch the video source. 508 }).margin(5) 509 Button('previewUri').onClick(() => { 510 this.previewUri = $r('app.media.poster2') // Switch the preview image. 511 }).margin(5) 512 513 Button('controls').onClick(() => { 514 this.showControls =! this.showControls // Specify whether to show the control bar. 515 }).margin(5) 516 } 517 Row() { 518 Button('start').onClick(() => { 519 this.controller.start() // Start playback. 520 }).margin(5) 521 Button('pause').onClick(() => { 522 this.controller.pause() // Pause playback. 523 }).margin(5) 524 Button('stop').onClick(() => { 525 this.controller.stop() // Stop playback. 526 }).margin(5) 527 Button('setTime').onClick(() => { 528 this.controller.setCurrentTime(10, SeekMode.Accurate) // Seek to the 10s position of the video. 529 }).margin(5) 530 } 531 Row() { 532 Button('rate 0.75').onClick(() => { 533 this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // Play the video at the 0.75x speed. 534 }).margin(5) 535 Button('rate 1').onClick(() => { 536 this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // Play the video at the 1x speed. 537 }).margin(5) 538 Button('rate 2').onClick(() => { 539 this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // Play the video at the 2x speed. 540 }).margin(5) 541 } 542 } 543 }} 544``` 545 546**Reference** 547 548[Video](../reference/apis-arkui/arkui-ts/ts-media-components-video.md#start) 549 550## How do I set state-specific styles for a component? (API version 9) 551 552 553**Solution** 554 555You can use the **stateStyles** attribute to set styles of a component for different states (stateless, pressed, disabled, focused, or clicked). 556 557**Example** 558 559``` 560//xxx.ts 561@Entry 562@Component 563struct StyleExample { 564 @State isEnable: boolean = true; 565 566 @Styles pressedStyles() { 567 .backgroundColor("#ED6F21") 568 .borderRadius(10) 569 .borderStyle(BorderStyle.Dashed) 570 .borderWidth(2) 571 .borderColor('#33000000') 572 .width(120) 573 .height(30) 574 .opacity(1) 575 } 576 build() { 577 Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) { 578 Text("pressed") 579 .backgroundColor('#0A59F7') 580 .borderRadius(20) 581 .borderStyle(BorderStyle.Dotted) 582 .borderWidth(2) 583 .borderColor(Color.Red) 584 .width(100) 585 .height(25) 586 .opacity(1) 587 .fontSize(14) 588 .fontColor(Color.White) 589 .stateStyles({ 590 pressed: this.pressedStyles 591 }) 592 .margin({ 593 bottom: 20 594 }) 595 .textAlign(TextAlign.Center) 596 } 597 .width(350) 598 .height(300) 599 } 600} 601``` 602 603**Reference** 604 605[Polymorphic Style](../reference/apis-arkui/arkui-ts/ts-universal-attributes-polymorphic-style.md) 606 607## What should I do if the flex width and height in the Scroll component conflicts with the scrolling? (API version 9) 608 609Applicable to: stage model 610 611**Symptom** 612 613When a container component with a fixed size is added to the **Scroll** component, a scrolling error occurs. 614 615**Solution** 616 617Do 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. 618 619 620## How does a component process click events in its child components? (API version 9) 621 622Applicable to: stage model 623 624When 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. 625 626**Example** 627 628``` 629class Model { 630 value: string 631} 632@Entry 633@Component 634struct EntryComponent { 635 test() { 636 console.log('testTag test in my component'); 637 } 638 build() { 639 Column() { 640 MyComponent({ title: { value: 'Hello World 2' }, count: 7, onClick: this.test }) // The defined method is transferred during initialization. 641 } 642 } 643} 644 645@Component 646struct MyComponent { 647 @State title: Model = { value: 'Hello World' } 648 @State count: number = 0 649 onClick: any; 650 private toggle: string = 'Hello World' 651 private increaseBy: number = 1 652 653 build() { 654 Column() { 655 Text(`${this.title.value}`).fontSize(30) 656 Button(`Click to increase count=${this.count}`) 657 .margin(20) 658 .onClick(() => { 659 // Change the count value of the internal state variable. 660 this.count += this.increaseBy 661 this.onClick.call(); 662 }) 663 } 664 } 665} 666``` 667 668 669## How do I implement a text input box that automatically brings up the soft keyboard? (API version 9) 670 671**Solution** 672 673You 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. 674 675**Reference** 676 677[Focus Control](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md) 678 679 680## How do I set the controlButton attribute for the SideBarContainer component? (API version 9) 681 682**Solution** 683 684Refer to the following sample code: 685 686``` 687@Entry 688@Component 689struct SideBarContainerExample { 690 normalIcon : Resource = $r("app.media.icon") 691 selectedIcon: Resource = $r("app.media.icon") 692 @State arr: number[] = [1, 2, 3] 693 @State current: number = 1 694 695 build() { 696 SideBarContainer(SideBarContainerType.Embed) 697 { 698 Column() { 699 ForEach(this.arr, (item, index) => { 700 Column({ space: 5 }) { 701 Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64) 702 Text("Index0" + item) 703 .fontSize(25) 704 .fontColor(this.current === item ? '#0A59F7' : '#999') 705 .fontFamily('source-sans-pro,cursive,sans-serif') 706 } 707 .onClick(() => { 708 this.current = item 709 }) 710 }, item => item) 711 }.width('100%') 712 .justifyContent(FlexAlign.SpaceEvenly) 713 .backgroundColor('#19000000') 714 715 716 Column() { 717 Text('SideBarContainer content text1').fontSize(25) 718 Text('SideBarContainer content text2').fontSize(25) 719 } 720 .margin({ top: 50, left: 20, right: 30 }) 721 } 722 .sideBarWidth(150) 723 .minSideBarWidth(50) 724 .controlButton({left:32, 725 top:32, 726 width:32, 727 height:32, 728 icons:{shown: $r("app.media.icon"), 729 hidden: $r("app.media.icon"), 730 switching: $r("app.media.icon")}}) 731 .maxSideBarWidth(300) 732 .onChange((value: boolean) => { 733 console.info('status:' + value) 734 }) 735 } 736} 737``` 738 739## How do I enable proactive component update? (API version 10) 740 741**Solution** 742 743In the **Canvas** component, there are two types of content: 1. content rendered with universal attributes of components, such as the background color and boarder; 7442. content drawn by the application through the **CanvasRenderingContext2D** API. The first type of content is updated through state variables. The second type of content is updated in the next frame once the API is called, thanks to the built-in dirty table feature of the API. You do not need to explicitly refresh this type of content. 745 746**Reference** 747 748[CanvasRenderingContext2D](../reference/apis-arkui/arkui-ts/ts-canvasrenderingcontext2d.md) 749 750## What should I do if the List component cannot scroll to the bottom with its height not specified? (API version 10) 751 752**Cause** 753 754If no height is set for a **List** component and the total height of its child components is greater than the height of its parent component, the component is displayed at the height of its parent component. In this case, if the **List** component has sibling nodes, part of it may be pushed outside of the display area of the parent component, making it seemingly unable to be scrolled to the bottom. 755 756**Solution** 757 758Add the **layoutWeight(1)** attribute for the **List** component so that it takes up the remaining space. 759 760**Reference** 761 762[Size](../reference/apis-arkui/arkui-ts/ts-universal-attributes-size.md) 763 764## How do I implement infinite data loading and display for scrolling with a water flow layout? (API version 10) 765 766**Solution** 767 7681. Use **LazyForEach** as a child node of the **WaterFlow** component. 769 7702. Determine whether the bottom is about to be reached in **onAppear** of the **FlowItem** component, and append new data to the **LazyForEach** data source in advance. Alternatively, determine whether the bottom is about to be reached based on the current index in the **onScrollIndex**<sup>11+</sup> event. 771 772**Reference** 773 774[High-Performance WaterFlow Development](../performance/waterflow_optimization.md) 775 776## How do I open a new page from a custom dialog box without closing the dialog box? (API version 10) 777 778**Solution** 779 780Obtain the **uiContext** instance of the main window and then call **router.push** to jump to the new page. 781 782**Reference** 783 784[Custom Dialog Box](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md) 785 786## Is there any update on ArkUI-X availability? Is there a roadmap for ArkUI-X? (API version 10) 787 788**Solution** 789 7901. Progress: ArkUI-X is now an open-source tool, with first version officially released on December 15, 2023. It runs Android and iOS, with support for desktop and web platforms well on the way. 791 7922. [Roadmap](https://gitee.com/arkui-x/docs/blob/master/en/roadmap) 793 794**Reference** 795 796[ArkUI-X](https://gitee.com/arkui-x) 797 798## How does an application track component data or state in the build process of custom components? (API version 10) 799 800**Symptom** 801 802Logs cannot be inserted into the **build** method of the UI. As a result, the application cannot detect the UI drawing process, which is inconvenient for UI debugging and fault locating. 803 804**Solution** 805 806Use the @Watch callback to listen for changes in state variables. If the callback function is executed, it indicates that the UI using the state variable will be re-rendered during the next VSync signal. 807 808The sample code is as follows: 809 810```ts 811@Prop @Watch('onCountUpdated') count: number = 0; 812@State total: number = 0; 813// @Watch callback 814onCountUpdated(propName: string): void { 815 this.total += this.count; 816} 817``` 818 819**Reference** 820 821[@Watch Decorator: Getting Notified of State Variable Changes](../quick-start/arkts-watch.md) 822 823## How are inheritance and encapsulation implemented for custom components in ArkUI? (API version 10) 824 825**Solution** 826 827In the declarative UI, custom components do not support inheritance. To extend functionality, you can draw on the combination mechanism and inherit, reuse, and transfer existing component attributes with the attribute modifier. 828 829## What parameter types and unit types do components support? When are they used? (API version 10) 830 831**Solution** 832 833ArkUI provides several pixel units:<br>px: physical pixel unit of the screen. 1 px indicates a pixel on the screen. lpx: logical pixel unit of the window. It is the ratio of the actual screen width to the logical width (configured by **designWidth**), representing the baseline width for page design. The size of an element is scaled at this ratio to the actual screen width. vp: virtual pixel unit. fp: font pixel unit. The formula for calculating vp is as follows: vp = px/(DPI/160). 834A virtual pixel (vp) describes the virtual size of a device for an application. It is different from the unit used by the screen hardware, pixel (px). Its use allows elements to have a consistent visual volume on devices with different densities. By default, the font pixel (fp) size is the same as that of the virtual pixel size. That is, 1 fp = 1 vp. If you select a larger font size in **Settings**, the actual font size is the virtual pixel size multiplied by the scale coefficient. That is, 1 fp = 1 vp \* scale. Percentage: The unit must be %, for example, **'10%'**. 835Resource: Size referenced from system or application resources. 836