• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# ArkUI动画/交互事件开发常见问题(ArkTS)
2
3
4## 焦点事件onBlur/onFocus回调无法触发(API 9)
5
6**问题现象**
7
8焦点事件onBlur/onFocus回调无法触发
9
10**解决措施**
11
12焦点事件默认情况下需要外接键盘的Tab键,或方向键触发,点击触发焦点事件需要添加焦点控制属性focusOnTouch。
13
14**参考链接**
15
16[焦点控制](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md)
17
18
19## scroll里面套一个grid,如何禁用grid的滑动事件(API 9)
20
21可以通过onScrollFrameBegin事件和scrollBy方法实现容器嵌套滚动。
22
23**参考链接**
24
25[容器嵌套滚动样例](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#示例2嵌套滚动实现方式一)
26
27
28## 如何实现一个组件不停地旋转(API 9)
29
30可以通过[属性动画](../reference/apis-arkui/arkui-ts/ts-animatorproperty.md)的方式实现。
31
32
33## 列表目前无法键盘上下滑动,是否能力不支持(API 9)
34
35**解决措施**
36
37有以下两种方案:
38
391. 需要在列表子项中添加focusable(true)进行获焦。
40
412. 在每个item的外层嵌套一个可获焦组件,例如Button。
42
43
44## 键盘移动焦点对象按下enter,为什么不会触发点击事件(API 9)
45
46组件的内置的点击事件和开发者自定义的onClick点击事件默认会和空格键绑定,并非与enter键绑定(UX规格)。
47
48
49## 多层组件嵌套button,如何阻止事件传递(API 9)
50
51可以通过将button组件绑定参数stopPropagation来控制冒泡传递。
52
53
54## 使用router或Navigator实现页面跳转时,如何关闭页面间转场动效(API 9)
55
561. 参考[页面间转场示例](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#示例)在当前页面和目标页面中定义pageTransition方法。
57
582. 将页面入场组件PageTransitionEnter和页面退场组件PageTransitionExit的动效参数duration都设置为0。
59
60
61## 在容器组件嵌套的场景下,如何解决手势拖拽事件出现错乱的问题(API 9)
62
63PanGesture用于触发拖动手势事件,滑动的最小距离distance默认为5vp时拖动手势识别成功。可以将distance值设为1,使拖动更灵敏,避免造成事件错乱。
64
65**参考链接**
66
67[PanGesture](../reference/apis-arkui/arkui-ts/ts-basic-gestures-pangesture.md)
68
69
70## 是否支持使用fontFamily属性设置不同的字体(API 9)
71
72默认字体'HarmonyOS Sans',且当前只支持这种字体。
73
74
75## 点击输入框时会拉起软键盘,点击button时软键盘关闭要如何实现(API 9)
76
77TextInput获取焦点会弹出输入法,失去焦点就会关闭软键盘,使用focusControl控制焦点即可关闭软键盘。
78
79**代码示例**
80
81```
82build() {
83  Column() {
84    TextInput()
85    Button(`hide`)
86      .key('button')
87      .onClick(()=>{
88        focusControl.requestFocus('button')
89      })
90  }
91}
92```
93
94
95## 当父组件绑定了onTouch,其子组件Button绑定了onClick,如何做到点击Button只响应Button的onClick,而不用响应父组件的onTouch(API 9)
96
97可以在Button组件中绑定onTouch,并在onTouch中使用stopPropagation()阻止onTouch冒泡传递到父组件阻止冒泡传递。
98
99**代码示例**
100
101```
102@Entry
103@Component
104struct Index {
105  build() {
106    Row() {
107      Button("点击我")
108        .width(100)
109        .backgroundColor('#f00')
110        .onClick(() => {
111          console.log("Button onClick");
112        })
113        .onTouch((e) => {
114          console.log("Button onTouch");
115          e.stopPropagation();
116        })
117    }
118    .onTouch(() => {
119      console.log("Row onTouch");
120    })
121  }
122}
123```
124
125
126## 绑定菜单后无法使用右键触发菜单(API 9)
127
128**解决措施**
129
130目前菜单仅支持点击、长按触发方式,没有右键方式。
131
132
133## 点击文本输入框,如何屏蔽系统默认键盘弹起行为(API 9)
134
135设置TextInput组件的focusable属性为false,此组件则不可获焦,就不会拉起系统默认的键盘。
136
137
138## 如何实现上下切换的页面间跳转动画(API 9)
139
140**问题现象**
141
142页面切换时如何实现上下切换动画
143
144**解决措施**
145
146可以使用pageTransition函数来实现页面转场效果,通过PageTransitionEnter和PageTransitionExit指定页面进入和退出的动画效果,将其slide属性设置为SlideEffect.Bottom,则页面入场时从下边划入,出场时滑出到下边,即可实现上下切换效果。
147
148**代码示例**
149
150```
151// Index.ets
152@Entry
153@Component
154struct PageTransition1 {
155  build() {
156    Stack({alignContent: Alignment.Bottom}) {
157      Navigator({ target: 'pages/Page1'}) {
158        Image($r('app.media.ic_banner01')).width('100%').height(200) // 图片存放在media文件夹下
159      }
160    }.height('100%').width('100%')
161  }
162  pageTransition() {
163    PageTransitionEnter({ duration: 500, curve: Curve.Linear }).slide(SlideEffect.Bottom)
164    PageTransitionExit({ duration: 500, curve: Curve.Ease }).slide(SlideEffect.Bottom)
165  }
166}
167```
168
169```
170// Page1.ets
171@Entry
172@Component
173struct PageTransition2 {
174  build() {
175    Stack({alignContent: Alignment.Bottom}) {
176      Navigator({ target: 'pages/Index'}) {
177        Image($r('app.media.ic_banner02')).width('100%').height(200) // 图片存放在media文件夹下
178      }
179    }.height('100%').width('100%')
180  }
181  pageTransition() {
182    PageTransitionEnter({ duration: 500, curve: Curve.Linear }).slide(SlideEffect.Bottom)
183    PageTransitionExit({ duration: 500, curve: Curve.Ease }).slide(SlideEffect.Bottom)
184  }
185}
186```
187
188**参考链接**
189
190[页面间转场](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md)
191
192## 自定义组件间如何实现从底部滑入滑出的效果(API 9)
193
194**问题现象**
195
196一个页面底部默认显示自定义组件A,点击自定义组件A,则A消失,自定义组件B从底部出现;点击自定义组件B,则组件B消失,A从底部出现。这个效果要如何实现?
197
198**解决措施**
199
200可以使用transition产生组件转场动画,其参数type用来设置组件变化场景,包括新增和删除;参数translate用来设置转场时的平移效果。注意transition需要配合animateTo才能生效,动效时长、曲线、延时跟随animateTo中的配置。
201
202**代码示例**
203
204```
205@Entry
206@Component
207struct ComponentTransition {
208  @State flag: boolean = true;
209
210  build() {
211    Stack({alignContent: Alignment.Bottom}) {
212        if (this.flag) {
213          ComponentChild1({ flag: $flag })
214            .transition({ type: TransitionType.Insert,translate: { x: 0, y: 200 } })
215        }
216        if (!this.flag) {
217          ComponentChild2({ flag: $flag })
218            .transition({ type: TransitionType.Insert, translate: { x: 0, y: 200 } })
219        }
220    }.height('100%').width('100%')
221  }
222}
223
224@Component
225struct ComponentChild1 {
226  @Link flag: boolean
227
228  build() {
229    Column() {
230      Image($r('app.media.ic_banner01'))
231        .width('100%')
232        .height(200)
233        .onClick(() => {
234          this.getUIContext()?.animateTo({ duration: 1000 }, () => {
235            this.flag = !this.flag;
236          })
237        })
238    }
239  }
240}
241
242@Component
243struct ComponentChild2 {
244  @Link flag: boolean
245
246  build() {
247    Column() {
248      Image($r('app.media.ic_banner02'))
249        .width('100%')
250        .height(200)
251        .onClick(() => {
252          this.getUIContext()?.animateTo({ duration: 1000 }, () => {
253            this.flag = !this.flag;
254          })
255        })
256    }
257  }
258}
259```
260
261**参考链接**
262
263[出现/消失转场](../ui/arkts-enter-exit-transition.md)
264
265
266## 文件管理器短按不响应(API 10)
267
268**问题现象**
269
270短按文件夹图标,如点击时长在200-500ms松手会触发文件管理器点击不响应。
271
272**原因分析**
273
274拖拽手势识别逻辑存在异常分支未处理,短按特定时间段松手会导致手势识别器处于pending状态,不再响应用户输入导致文件管理器出现卡死现象。
275
276**解决措施**
277
278长按文件图标或者空白区域即可恢复。
279
280## 如何自定义处理父子组件间的事件传递(API 10)
281
282**解决措施**
283
2841.系统会基于触摸测试来收集需要响应事件的控件,测试的顺序由父组件向子组件蔓延,后续手势的识别和竞争都基于测试结果进行;
285
2862.应用可通过改变组件上hitTestBehavior的值来改变系统对其的hittest结果;
287
2883.可通过自定义事件和自定义手势判定能力来细化对手势识别和竞争结果的干预。
289
290**参考链接**
291
2921.[hitTestBehavior](../reference/apis-arkui/arkui-ts/ts-universal-attributes-hit-test-behavior.md)
293
2942.[自定义事件分发](../reference/apis-arkui/arkui-ts/ts-universal-attributes-on-child-touch-test.md)
295
2963.[自定义手势判定](../reference/apis-arkui/arkui-ts/ts-gesture-customize-judge.md)
297
298## 如何实现对列表的列表项进行拖动时,其他列表项自动补位和动态排列的效果(API 10)
299
300**解决措施**
301
3021.为列表或宫格项(item)添加拖拽能力,使能draggable,并注册onDragStart;
303
3042.在onDragStart回调中将所拖条目设置visibility为HIDDEN状态;
305
3062.在列表或宫格项(item)上注册onDragMove监听拖起的移动事件;
307
3083.拖动过程中,通过onDragMove的event参数获取到拖拽跟手点坐标;
309
3104.计算跟手点坐标与item中线的距离关系,当重合时,启动挤位动效;
311
3125.Item布局信息可通过componentUtils API获取到;
313
3146.挤位动效通过animateTo来改变datasource里的index,触发list的排序动效;
315
3167.落位动效可通过自定义动效完成。
317
318 **示例代码**
319
320```ts
321// 起拖时记录拖拽item
322  .onDragStart((event?: DragEvent, extraParams?: string) => {
323    this.dragIndex = Number(item.data)
324    this.dragItem = item
325  })
326  // 进入新的item时执行挤位效果
327  .onDragEnter((event?: DragEvent, extraParams?: string) => {
328    if (Number(item.data) != this.dragIndex) {
329      let current = this.dataSource.findIndex((element) => element.data === this.dragItem.data)
330      let index = this.dataSource.findIndex((element) => element.data === item.data)
331      this.getUIContext()?.animateTo({
332        curve: curves.interpolatingSpring(0, 1, 400, 38)
333      }, () => {
334        this.dataSource.splice(current, 1)
335        this.dataSource.splice(index, 0, this.dragItem)
336      })
337    }
338  })
339   // 释放时自定义落位动效,在释放位置开始对dragItem执行动效
340  .onDrop((dragEvent: DragEvent) => {
341    dragEvent.useCustomDropAnimation = true;
342    // 获取到落位位置
343    let downLocation = getInspectorByKey(item.data)
344    let currentLocation = dragEvent.getPreviewRect()
345    this.dragItem.scale = 1.05
346    this.getUIContext()?.animateTo({
347      curve: curves.interpolatingSpring(14, 1, 170, 17)
348    }, () => {
349      this.dragItem.scale = 1
350    })
351  })
352```
353
354## 拖拽过程中出现中转站(API 9)
355
356**问题现象**
357
358图片拖拽过程中会出现中转站窗口。
359
360**原因分析**
361
362Image组件默认支持拖拽,中转站感知到拖拽后会主动拉起。
363
364**解决措施**
365
3661.设置Image组件的draggable属性为false。
367
3682.在设置->系统->中转站中关闭“拖拽时启动”功能。
369
370**参考链接**
371
372[draggable](../reference/apis-arkui/arkui-ts/ts-basic-components-image.md#draggable9)