• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ArkUI组件开发常见问题(ArkTS)
2
3
4## 自定义弹窗能否在ts文件中定义和使用(API 9)
5
6自定义弹窗的定义和初始化需要用到属于ArkTS语法内容,必须在ets后缀文件中定义使用,不能在ts后缀文件中定义使用。
7
8**参考链接**
9
10[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
11
12
13## 自定义弹窗中的变量如何传递给页面(API 9)
14
15**问题现象**
16
17在自定义弹窗内定义的变量内容,在关闭弹窗或变量变化时需要及时传递给页面,可以通过何种方式传递?
18
19**解决措施**
20
21- 方式一:使用组件的状态变量传递。
22
23- 方式二:在初始化弹窗时,传递一个方法给自定义弹窗,在自定义弹窗中触发该方法,弹窗中变量作为方法的参数。
24
25- 方式三:使用AppStorage或LocalStorage方式管理页面状态,实现自定义弹窗和页面之间状态的共享。
26
27**代码示例**
28
29- 方式一:
30
31  ```
32  @CustomDialog
33  struct CustomDialog01 {
34    @Link inputValue: string
35    controller: CustomDialogController
36    build() {
37      Column() {
38        Text('Change text').fontSize(20).margin({ top: 10, bottom: 10 })
39        TextInput({ placeholder: '', text: this.inputValue }).height(60).width('90%')
40          .onChange((value: string) => {
41            this.inputValue = value
42          })
43      }
44    }
45  }
46
47  @Entry
48  @Component
49  struct DialogDemo01 {
50    @State inputValue: string = 'click me'
51    dialogController: CustomDialogController = new CustomDialogController({
52      builder: CustomDialog01({
53        inputValue: $inputValue
54      })
55    })
56
57    build() {
58      Column() {
59        Button(this.inputValue)
60          .onClick(() => {
61            this.dialogController.open()
62          }).backgroundColor(0x317aff)
63      }.width('100%').margin({ top: 5 })
64    }
65  }
66  ```
67
68- 方式二:
69
70  ```
71  @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- 方式三:
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## 如何获取组件的宽高(API 9)
151
152**问题现象**
153
154组件的宽高信息用于计算布局区域大小以及偏移量等内容,如何获取宽高信息?
155
156**解决措施**
157
158- 方式一:使用组件区域变化事件onAreaChange,在组件初始化或组件尺寸发生变化时触发。
159
160- 方式二:在点击或触摸事件中,事件的回调信息中存在目标元素的区域信息。
161
162**参考链接**
163
164[组件区域变化事件](../reference/apis-arkui/arkui-ts/ts-universal-component-area-change-event.md),[点击事件](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md),[触摸事件](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md)
165
166
167## 如何一键清空TextInput、TextArea组件内容(API 9)
168
169**问题现象**
170
171TextInput,TextArea组件输入多字符后,需要实现点击清空。
172
173**解决措施**
174
175将状态变量赋值给TextInput或TextArea组件的text属性,在做点击清空事件时为状态变量赋值空字符串。
176
177**代码示例**
178
179```ts
180// xxx.ets
181@Entry
182@Component
183struct Index {
184  @State text: string = 'Hello World';
185  controller: TextInputController = new TextInputController();
186
187  build() {
188    Row() {
189      Column() {
190        TextInput({
191          placeholder: 'Please input your words.', text: this.text,
192          controller: this.controller
193        }).onChange((value: string) => {
194          this.text = value;
195        })
196        Button("Clear TextInput").onClick(() => {
197          this.text = "";
198        })
199      }
200      .width('100%')
201    }
202    .height('100%')
203  }
204}
205```
206
207
208## 如何设置自定义弹窗位置(API 9)
209
210**问题现象**
211
212自定义弹窗当前默认在窗口居中显示,当自定义弹窗需要与窗口边框对齐是需要设置自定义弹窗的对齐方式。
213
214**解决措施**
215
216初始化自定义弹窗时,通过alignment参数设置对齐方式,通过offset设置弹窗偏移量。
217
218**参考链接**
219
220[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
221
222
223## 如何隐藏容器组件的溢出内容(API 9)
224
225**问题现象**
226
227当容器组件内容溢出时,表现为子组件边缘超出容器组件,需要进行隐藏设置。
228
229**解决措施**
230
231将通用属性-形状裁剪clip属性设置为true,表示按照容器边缘轮廓进行裁剪。此属性默认为false,表示不进行裁剪隐藏。
232
233**参考链接**
234
235[形状裁剪](../reference/apis-arkui/arkui-ts/ts-universal-attributes-sharp-clipping.md)
236
237
238## 自定义弹窗大小如何自适应内容(API 9)
239
240**问题现象**
241
242当自定义弹窗中存在可变化区域大小的子组件时,弹窗大小需要跟随自适应。
243
244**解决措施**
245
246- 方式一:采用弹窗容器默认样式。在默认样式中,弹窗容器高度自适应子节点,最大可为窗口高度的90%;弹窗容器的宽度根据栅格系统自适应,不跟随子节点变化。
247
248- 方式二:当显示设置customStyle为true时,弹窗宽高跟随子节点内容适应。
249
250**参考链接**
251
252[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
253
254
255## 如何理解自定义弹窗中的gridCount参数(API 9)
256
257gridCount参数是指弹窗宽度占栅格列数的个数。系统把窗口宽等分,等分的份数即为栅格列数,不同设备栅格列数不同。假设设备屏幕密度值在320vp<=水平宽度<600vp,所以栅格列数是4,则gridCount的有效值在[1, 4]。
258
259注意:仅采用弹窗默认样式时设置有效。
260
261**参考链接**
262
263[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
264
265
266## 如何去除自定义弹窗的白色背景(API 9)
267
268**问题现象**
269
270使用自定义弹窗时,默认样式中存在白色背景。
271
272**解决措施**
273
274需要采用自定义样式来消除自定义弹窗的白色背景:
275
2761. 在初始化自定义弹窗时设置customStyle为true。
277
2782. 在定义弹窗时设置组件背景色backgroundColor。
279
280**参考链接**
281
282[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
283
284
285## TextInput组件密码模式下,右边的眼睛图标能否支持自定义(API 9)
286
287**问题现象**
288
289TextInput组件设置type为InputType.Password时,右侧出现眼睛图标,不能修改图标样式。
290
291**解决措施**
292
293当前图标不支持自定义,可使用TextInput的showPasswordIcon属性隐藏图标,使用Image组件替代控制TextInput组件的type。
294
295**参考链接**
296
297[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md)
298
299
300## TextInput的onSubmit事件如何使用(API 9)
301
302**问题现象**
303
304TextInput的onSubmit事件怎么触发,以及事件回调的参数类型代表的含义。
305
306**解决措施**
307
308onSubmit事件在外接键盘或软键盘回车时触发该回调,回调的参数为当前软键盘回车键类型。通过TextInput的enterKeyType属性可以设置输入法回车键类型,软键盘回车键样式需要输入法的支持。
309
310**参考链接**
311
312[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md)
313
314
315## TextInput在聚焦时如何使光标回到起点(API 9)
316
317**问题现象**
318
319TextInput组件在聚焦时,光标位置会自动根据触摸点位置变化,如何使得聚焦时光标固定显示在起点位置?
320
321**解决措施**
322
3231. TextInput组件绑定onEditChange事件,该事件TextInput可进行输入时触发。
324
3252. 在事件回调用TextInputController.caretPosition方法设置光标位置,不过需要用到setTimeout延迟方法。
326
327**代码示例**
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**参考链接**
351
352[TextInput组件](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md)
353
354
355## 如何获取可滚动组件的当前滚动偏移量(API 9)
356
357**问题现象**
358
359可滚动组件包含List,Grid,Scroll等,在发生滚动时如何获取滚动偏移量?
360
361**解决措施**
362
3631. 可滚动组件在初始化时可设置scroller参数,绑定滚动控制器。
364
3652. 通过控制器的currentOffset方法可获取水平和竖直方向的滚动偏移量。
366
367**参考链接**
368
369[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#currentoffset)
370
371
372## 如何实现文本竖向排列(API 9)
373
374**问题现象**
375
376使用Text组件时,无法将文本排列方向设置为竖向排列。
377
378**解决措施**
379
380Text组件当前文本排列方向固定为横向排列,要设置为竖向排列,可将文件拆分,使用Flex容器组件装填,设置主轴方向为竖向。
381
382**代码示例**
383
384```
385@Entry
386@Component
387struct Index15 {
388  private message: string = '本文档适用于应用开发的初学者。通过构建一个简单的具有页面跳转/返回功能的应用,快速了解工程目录的主要文件,熟悉应用开发流程。';
389  build() {
390    Flex({ direction: FlexDirection.Column, wrap: FlexWrap.Wrap }) {
391      ForEach(this.message.split(''), (item, index) => {
392        Text(item)
393          .fontSize(30)
394          .flexShrink(0)
395      })
396    }
397  }
398}
399```
400
401
402## 如何将Ability的UI界面设置成透明(API 9)
403
404**问题现象**
405
406如何设置Ability的UI界面为透明
407
408**解决措施**
409
410将最上层容器组件背景色设置为透明,然后通过设置XComponent组件的opacity属性值为0.01来实现。
411
412示例:
413
414```
415build() {
416  Stack() {
417    XComponent({
418    id: 'componentId',
419    type: 'surface',
420    })
421    .width('100%')
422    .height('100%')
423    .opacity(0.01)
424    // 页面内容
425  }
426  .width('100%')
427  .height('100%')
428  .backgroundColor('rgba(255,255,255, 0)')
429}
430```
431
432
433## constraintSize尺寸设置不生效(API 9)
434
435适用于Stage模型。
436
437**问题现象**
438
439constraintSize约束组件尺寸时,子组件内设置百分比宽度,例如width('100%')会采用constraintSize约束中的最大宽乘百分比,导致撑开组件,看起来constraintSize设置没生效。
440
441**解决措施**
442
443可以在外层使用Scroll组件,设置constraintSize,当子组件占用空间超过设置的约束值时,会显示滚动条。
444
445
446## 如何将背景颜色设置为透明(API 9)
447
448**解决措施**
449
450将backgroundColor设置为 '\#00000000'。
451
452
453## Scroll组件滚动到达不了最底部(API 9)
454
455适用于Stage模型。
456
457**问题现象**
458
459Scroll组件在未设置高度情况下,默认为窗口高度,当滚动区域外存在其他组件时,滚动底部区域会出现遮挡。
460
461**解决措施**
462
463Scroll组件需要设置Scroll高度,或者使用Flex布局限制Scroll高度。
464
465
466## 如何自定义Video组件控制栏样式(API 9)
467
468适用于Stage模型。
469
470**解决措施**
471
4721. 通过设置属性controls为false关闭默认控制栏。
473
4742. 设置Video组件的controller。
475
4763. 通过ArkTS实现自定义的控制栏,并通过VideoController控制视频播放。
477
478**代码示例**
479
480```ts
481// xxx.ets
482@Entry
483@Component
484struct VideoCreateComponent {
485  @State videoSrc: Resource = $rawfile('video1.mp4')
486  @State previewUri: Resource = $r('app.media.poster1')
487  @State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_X
488  @State isAutoPlay: boolean = false
489  @State showControls: boolean = false
490  controller: VideoController = new VideoController()
491
492  build() {
493    Column() {
494      Video({
495        src: this.videoSrc,
496        previewUri: this.previewUri,
497        currentProgressRate: this.curRate,
498        controller: this.controller
499      })
500        .width('100%')
501        .height(600)
502        .autoPlay(this.isAutoPlay)
503        .controls(this.showControls)
504        .onStart(() => {
505          console.info('onStart')
506        })
507        .onPause(() => {
508          console.info('onPause')
509        })
510        .onFinish(() => {
511          console.info('onFinish')
512        })
513        .onError(() => {
514          console.info('onError')
515        })
516        .onPrepared((e) => {
517          console.info('onPrepared is ' + e.duration)
518        })
519        .onSeeking((e) => {
520          console.info('onSeeking is ' + e.time)
521        })
522        .onSeeked((e) => {
523          console.info('onSeeked is ' + e.time)
524        })
525        .onUpdate((e) => {
526          console.info('onUpdate is ' + e.time)
527        })
528      Row() {
529        Button('src').onClick(() => {
530          this.videoSrc = $rawfile('video2.mp4') // 切换视频源
531        }).margin(5)
532        Button('previewUri').onClick(() => {
533          this.previewUri = $r('app.media.poster2') // 切换视频预览海报
534        }).margin(5)
535
536        Button('controls').onClick(() => {
537          this.showControls = !this.showControls // 切换是否显示视频控制栏
538        }).margin(5)
539      }
540
541      Row() {
542        Button('start').onClick(() => {
543          this.controller.start() // 开始播放
544        }).margin(5)
545        Button('pause').onClick(() => {
546          this.controller.pause() // 暂停播放
547        }).margin(5)
548        Button('stop').onClick(() => {
549          this.controller.stop() // 结束播放
550        }).margin(5)
551        Button('setTime').onClick(() => {
552          this.controller.setCurrentTime(10, SeekMode.Accurate) // 精准跳转到视频的10s位置
553        }).margin(5)
554      }
555
556      Row() {
557        Button('rate 0.75').onClick(() => {
558          this.curRate = PlaybackSpeed.Speed_Forward_0_75_X // 0.75倍速播放
559        }).margin(5)
560        Button('rate 1').onClick(() => {
561          this.curRate = PlaybackSpeed.Speed_Forward_1_00_X // 原倍速播放
562        }).margin(5)
563        Button('rate 2').onClick(() => {
564          this.curRate = PlaybackSpeed.Speed_Forward_2_00_X // 2倍速播放
565        }).margin(5)
566      }
567    }
568  }
569}
570```
571
572**参考链接**
573
574[Video](../reference/apis-arkui/arkui-ts/ts-media-components-video.md#start)
575
576## 如何设置组件不同状态下的样式(API 9)
577
578**问题现象**
579
580对应组件的不同状态(如无状态、按下、禁用、聚焦、点击),显示不同的样式。
581
582**解决措施**
583
584使用多态样式,在组件的StateStyles接口中,定义组件不同状态下的样式。
585
586**代码示例**
587
588```
589//xxx.ts
590@Entry
591@Component
592struct StyleExample {
593  @State isEnable: boolean = true;
594
595  @Styles pressedStyles() {
596    .backgroundColor("#ED6F21")
597    .borderRadius(10)
598    .borderStyle(BorderStyle.Dashed)
599    .borderWidth(2)
600    .borderColor('#33000000')
601    .width(120)
602    .height(30)
603    .opacity(1)
604  }
605  build() {
606    Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center}) {
607      Text("pressed")
608        .backgroundColor('#0A59F7')
609        .borderRadius(20)
610        .borderStyle(BorderStyle.Dotted)
611        .borderWidth(2)
612        .borderColor(Color.Red)
613        .width(100)
614        .height(25)
615        .opacity(1)
616        .fontSize(14)
617        .fontColor(Color.White)
618        .stateStyles({
619          pressed: this.pressedStyles
620        })
621        .margin({
622          bottom: 20
623        })
624        .textAlign(TextAlign.Center)
625    }
626    .width(350)
627    .height(300)
628  }
629}
630```
631
632**参考链接**
633
634[多态样式](../reference/apis-arkui/arkui-ts/ts-universal-attributes-polymorphic-style.md)
635
636## Scroll内Flex加宽高与滑动冲突(API 9)
637
638适用于Stage模型。
639
640**问题现象**
641
642当在Scroll组件中添加容器组件,并设置该容器组件的尺寸时,会破坏滚动布局。
643
644**解决措施**
645
646Scroll组件中的容器组件不设置尺寸,大小由内容撑开。
647
648
649## 父组件中如何处理子组件内点击事件(API 9)
650
651适用于Stage模型。
652
653在父组件中初始化子组件时,将父组件中定义的方法,传递给子组件,在子组件中调用该方法,类似于变量传递。
654
655**代码示例**
656
657```
658class Model {
659  value: string = "";
660}
661
662@Entry
663@Component
664struct EntryComponent {
665  test() {
666    console.log('testTag test in my component');
667  }
668
669  build() {
670    Column() {
671      MyComponent({ title: { value: 'Hello World 2' }, count: 7, click: this.test }) //初始化时传递定义的方法
672    }
673  }
674}
675
676@Component
677struct MyComponent {
678  @State title: Model = { value: 'Hello World' };
679  @State count: number = 0;
680  click: () => void = () => {
681  };
682  private increaseBy: number = 1;
683
684  build() {
685    Column() {
686      Text(`${this.title.value}`).fontSize(30)
687      Button(`Click to increase count=${this.count}`)
688        .margin(20)
689        .onClick(() => {
690          // 修改内部状态变量count
691          this.count += this.increaseBy;
692          this.click();
693        })
694    }
695  }
696}
697```
698
699
700## 如何主动拉起软键盘(API 9)
701
702**解决措施**
703
704可以通过focusControl.requestFocus控制输入框获焦,组件获焦后会自动弹起软键盘
705
706**参考链接**
707
708焦点控制:[焦点控制](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md)
709
710
711## SideBarContainer如何设置controlButton属性(API 9)
712
713**解决措施**
714
715示例代码:
716
717```
718@Entry
719@Component
720struct SideBarContainerExample {
721  normalIcon: Resource = $r("app.media.icon")
722  selectedIcon: Resource = $r("app.media.icon")
723  @State arr: number[] = [1, 2, 3]
724  @State current: number = 1
725
726  build() {
727    SideBarContainer(SideBarContainerType.Embed) {
728      Column() {
729        ForEach(this.arr, (item, index) => {
730          Column({ space: 5 }) {
731            Image(this.current === item ? this.selectedIcon : this.normalIcon).width(64).height(64)
732            Text("Index0" + item)
733              .fontSize(25)
734              .fontColor(this.current === item ? '#0A59F7' : '#999')
735              .fontFamily('source-sans-pro,cursive,sans-serif')
736          }
737          .onClick(() => {
738            this.current = item
739          })
740        }, item => item)
741      }.width('100%')
742      .justifyContent(FlexAlign.SpaceEvenly)
743      .backgroundColor('#19000000')
744
745
746      Column() {
747        Text('SideBarContainer content text1').fontSize(25)
748        Text('SideBarContainer content text2').fontSize(25)
749      }
750      .margin({ top: 50, left: 20, right: 30 })
751    }
752    .sideBarWidth(150)
753    .minSideBarWidth(50)
754    .controlButton({
755      left: 32,
756      top: 32,
757      width: 32,
758      height: 32,
759      icons: { shown: $r("app.media.icon"),
760        hidden: $r("app.media.icon"),
761        switching: $r("app.media.icon") }
762    })
763    .maxSideBarWidth(300)
764    .onChange((value: boolean) => {
765      console.info('status:' + value)
766    })
767  }
768}
769```
770
771## 如何实现主动控制组件刷新(API 10)
772
773**解决措施**
774
775Canvas组件最终的显示内容分两种,一种是组件通用属性的绘制内容,比如背景色,boarder等这类组件属性方法设置的渲染属性,这类属性是可以通过状态变量驱动更新的。
776另一种是通过CanvasRenderingContext2D绘制接口由应用自行绘制的内容。该类命令时绘制接口不响应状态变量,该类接口内置表脏功能,只要调用就会在下一帧刷新绘制内容,不需要开发者显式刷新。
777
778**参考链接**
779
780[CanvasRenderingContext2D](../reference/apis-arkui/arkui-ts/ts-canvasrenderingcontext2d.md)
781
782## 怎么解决列表组件List在不设置高度的情况下,会出现滑动不到底的问题(API 10)
783
784**原因分析**
785
786List没有设置高度时,如果子组件总高度大于List父组件的高度时,List会取List父组件高度。如果List有其他兄弟节点,可能会吧List部分顶出父组件显示区域外,看起来像是划不到底部。
787
788**解决措施**
789
790List组件设置layoutWeight(1)属性,将剩余空间全部分配给List组件。
791
792**参考链接**
793
794[尺寸设置](../reference/apis-arkui/arkui-ts/ts-universal-attributes-size.md)
795
796## 如何实现瀑布流滑动时,数据的无限加载和显示(API 10)
797
798**解决措施**
799
8001.使用LazyForEach做瀑布流子节点。
801
8022.参考WaterFlow高性能开发指导在FlowItem的onAppear中判断是否即将触底,提前在LazyForEach数据源尾部新增数据;或在onScrollIndex11+事件中根据当前index进行判断。
803
804**参考链接**
805
806[WaterFlow高性能开发指导](../performance/waterflow_optimization.md)
807
808## customDialog中调用router.push启动新页面,会把customDialog关闭,怎么实现在不关闭弹窗的前提下启动新页面(API 10)
809
810**解决措施**
811
812开发者在路由跳转时,需要获取到主窗口的uiContext,再调用路由跳转。
813
814**参考链接**
815
816[自定义弹窗](../reference/apis-arkui/arkui-ts/ts-methods-custom-dialog-box.md)
817
818## 当前ArkUI-X的支持进展如何,有无明确路线图(API 10)
819
820**解决措施**
821
8221.进展:ArkUI-X当前已经开源,首版本已于2023-12-15正式发布,当前支持Android、iOS跨平台;另外,也在探索和试验桌面平台与Web平台的支持。
823
8242.[路线图](https://gitee.com/arkui-x/docs/blob/master/zh-cn/roadmap/ArkUI-X-roadmap-2023.md)825
826**参考链接**
827
828[ArkUI-X](https://gitee.com/arkui-x)
829
830## 应用如何在自定义组件的构建流程里跟踪组件数据或者状态(API 10)
831
832**问题现象**
833
834UI的构建build方法内无法插入日志,导致应用无法感知UI绘制流程,不利于调试UI,定位UI问题。
835
836**解决措施**
837
838使用@Watch回调来监测状态变量的变化,如果执行回调函数,说明在下一次vysnc信号发送时,使用该状态变量的UI会刷新绘制。
839
840示例代码如下:
841
842```ts
843@Prop @Watch('onCountUpdated') count: number = 0;
844@State total: number = 0;
845// @Watch 回调
846onCountUpdated(propName: string): void {
847  this.total += this.count;
848}
849```
850
851**参考链接**
852
853[@Watch装饰器:状态变量更改通知](../ui/state-management/arkts-watch.md)
854
855## 自定义component不支持继承语法,针对其他框架支持的自定义组件继承及封装能力,ArkUI的解决方案是什么(API 10)
856
857**解决措施**
858
859对于声明式的自定义组件场景,不会提供继承的能力,需要使用组合的方式进行扩展,并结合后续提供的Modifier机制进行对现有组件属性的继承、复用和传递。
860
861## 组件支持的参数类型及参数单位类型区别是什么,使用场景是什么(API 10)
862
863**解决措施**
864
865屏幕像素单位px(pixel),表示屏幕上的实际像素,1px代表设备屏幕上的一个像素点。视窗逻辑像素单位lpx,lpx单位为实际屏幕宽度与逻辑宽度(通过designWidth配置)的比值,标识页面设计基准宽度。以此为基准,根据实际设备宽度来缩放元素大小。距离使用vp(virtual pixel),字体大小使用fp(font pixel),虚拟像素单位vp(virtual pixel),vp具体计算公式为:vp= px/(DPI/160)。
866以屏幕相对像素为单位, 是一台设备针对应用而言所具有的虚拟尺寸(区别于屏幕硬件本身的像素单位)。它提供了一种灵活的方式来适应不同屏幕密度的显示效果,使用虚拟像素,使元素在不同密度的设备上具有一致的视觉体量。字体像素单位fp(font pixel),字体像素(font pixel)大小默认情况下与vp相同,即默认情况下1fp=1vp。如果用户在设置中选择了更大的字体,字体的实际显示大小就会在vp的基础上乘以scale系数,即1fp=1vp*scale。Percentage - 需要指定以%像素单位,如'10%'。
867Resource - 资源引用类型,引入系统资源或者应用资源中的尺寸。
868
869## Surface模式下的XComponent组件在设置RenderFit后如果出现显示异常,该如何调整获取正确的显示效果(API 10)
870
871**解决措施**
872
873当Surface模式下的XComponent组件其内容与组件尺寸不一致时,可通过设置[renderFit](../reference/apis-arkui/arkui-ts/ts-universal-attributes-renderfit.md#renderfit18)属性,以调整绘制内容在组件尺寸范围内的布局方式,例如拉伸、居中、等比缩放等。
874在API version 18之前,Surface模式下的XComponent组件的[renderFit](../reference/apis-arkui/arkui-ts/ts-universal-attributes-renderfit.md#renderfit18)属性仅支持设置为RenderFit.RESIZE_FILL;如果设置为其他属性值可能会在部分机型出现显示异常。如果确实需要设置RESIZE_FILL之外的属性值,可以通过升级至API version 18或在XComponent组件的id字段中包含"RenderFitSurface"关键字来修正显示效果(在API version 18前)。
875
876示例代码如下:
877
878```ts
879// xxx.ets
880@Entry
881@Component
882struct Index {
883  @State xc_width: number = 500;
884  @State xc_height: number = 700;
885  myXComponentController: XComponentController = new XComponentController();
886
887  build() {
888    Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Start }) {
889      XComponent({
890        id: 'myXComponent_RenderFitSurface', // 当id的字符串中包含"RenderFitSurface"时,可以使RenderFit显示正确。
891        type: XComponentType.SURFACE,
892        controller: this.myXComponentController
893      })
894        .width(this.xc_width)
895        .height(this.xc_height)
896        .renderFit(RenderFit.CENTER)
897    }
898    .width('100%')
899    .height('100%')
900  }
901}
902
903```