• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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