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