1# ArkUI Animation/Interaction Event Development (ArkTS) 2 3 4## What should I do if the onBlur and onFocus callbacks cannot be triggered? (API version 9) 5 6**Symptom** 7 8The **onBlur** and **onFocus** callbacks of the focus event cannot be triggered. 9 10**Solution** 11 12Check the trigger device. By default, the focus event (and the **onBlur** and **onFocus** callbacks) can be triggered only by the Tab button and arrow buttons on the connected keyboard. To enable the focus event to be triggered by a touch, add the **focusOnTouch** attribute for the target component. 13 14**Reference** 15 16[Focus Control](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md) 17 18 19## How do I disable the scroll event of a Grid nested in the Scroll? (API version 9) 20 21Implement nested scrolling of the containers, by using the **onScrollFrameBegin** event and the **scrollBy** method. 22 23**Reference** 24 25[Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md#example-2). 26 27 28## How do I enable a component to rotate continuously? (API version 9) 29 30You can use [property animation](../reference/apis-arkui/arkui-ts/ts-animatorproperty.md) to that effect. 31 32 33## How do I scroll a list with the keyboard? (API version 9) 34 35**Solution** 36 37Use either of the following: 38 39- Add **focusable(true)** to the list item to enable it to obtain focus. 40 41- Nest a focusable component, for example, **Button**, at the outer layer of each item. 42 43 44## Why is the click event not triggered for the focused component upon the press of the Enter key after keyboard navigation? (API version 9) 45 46By default, the built-in click event of the component and the custom **onClick** click event are bound to the space bar instead of the Enter key. 47 48 49## How do I block event bubbling when a button is nested in multi-layer components? (API version 9) 50 51You can bind the button to the **stopPropagation** parameter. 52 53 54## How do I disable the page transition effect when the router or navigator is used for page transition? (API version 9) 55 561. Define the **pageTransition** method for the current and target pages, by following instructions in [Example](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md#example). 57 582. Set the **duration** parameter of both **PageTransitionEnter** and **PageTransitionExit** to **0**. 59 60 61## How do I fix misidentification of the pan gesture where container nesting is involved? (API version 9) 62 63The pan gesture requires a minimum 5 vp movement distance of a finger on the screen. You can set the **distance** parameter in **PanGesture** to **1** so that the pan gesture can be more easily recognized. 64 65**Reference** 66 67[PanGesture](../reference/apis-arkui/arkui-ts/ts-basic-gestures-pangesture.md) 68 69 70## Can I use the fontFamily attribute to set different fonts? (API version 9) 71 72No. Currently, only the default font, HarmonyOS Sans, is supported. 73 74 75## How do I implement a text input box that shows a soft keyboard when touched and hides the soft keyboard when a button is touched? (API version 9) 76 77Use **focusControl** for the **TextInput** component to control its focus. The **TextInput** component shows a soft keyboard when it gains focus and hides the soft keyboard when it loses focus. 78 79**Example** 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## How do I implement a button that only responds to the bound onClick event, but not the onTouch event bound to the button's parent component? (API version 9) 96 97Bind the **onTouch** event to the **Button** component and use **stopPropagation()** in the event to prevent the event from bubbling up to the parent component. 98 99**Example** 100 101``` 102build() { 103 Row() { 104 Button ("Click Me") 105 .width(100) 106 .width(100) 107 .backgroundColor('#f00') 108 .onClick(()=>{ 109 console.log("Button onClick") 110 }) 111 .onTouch((e) => { 112 console.log("Button onTouch") 113 e.stopPropagation() 114 }) 115 } 116 .onTouch(() => { 117 console.log("Row onTouch") 118 }) 119} 120``` 121 122 123## Why is the menu bound to a component not displayed when the component is right-clicked? (API version 9) 124 125**Solution** 126 127Currently, the menu is displayed when the bound component is clicked or long pressed. 128 129 130## How do I prevent the TextInput component from bringing up the default keyboard? (API version 9) 131 132Set the **focusable** attribute of the **TextInput** component to **false**. In this way, the component is not focusable and therefore will not bring up the keyboard. 133 134 135## How do I implement the slide up and slide down effect for page transition? (API version 9) 136 137 138 139 140 141**Solution** 142 143You can use the **pageTransition** API to implement the page transition effect. Specifically, set the **slide** attribute in **PageTransitionEnter** and **PageTransitionExit** to **SlideEffect.Bottom**. In this way, the page slides in and out from the bottom. 144 145**Example** 146 147``` 148// Index.ets 149@Entry 150@Component 151struct PageTransition1 { 152 build() { 153 Stack({alignContent: Alignment.Bottom}) { 154 Navigator({ target: 'pages/Page1'}) { 155 Image($r('app.media.ic_banner01')).width('100%').height(200) // Save the image in the media folder. 156 } 157 }.height('100%').width('100%') 158 } 159 pageTransition() { 160 PageTransitionEnter({ duration: 500, curve: Curve.Linear }).slide(SlideEffect.Bottom) 161 PageTransitionExit({ duration: 500, curve: Curve.Ease }).slide(SlideEffect.Bottom) 162 } 163} 164``` 165 166``` 167// Page1.ets 168@Entry 169@Component 170struct PageTransition2 { 171 build() { 172 Stack({alignContent: Alignment.Bottom}) { 173 Navigator({ target: 'pages/Index'}) { 174 Image($r('app.media.ic_banner02')).width('100%').height(200) // Save the image in the media folder. 175 } 176 }.height('100%').width('100%') 177 } 178 pageTransition() { 179 PageTransitionEnter({ duration: 500, curve: Curve.Linear }).slide(SlideEffect.Bottom) 180 PageTransitionExit({ duration: 500, curve: Curve.Ease }).slide(SlideEffect.Bottom) 181 } 182} 183``` 184 185**Reference** 186 187[Page Transition](../reference/apis-arkui/arkui-ts/ts-page-transition-animation.md) 188 189## How do I configure custom components to slide in and out from the bottom? (API version 9) 190 191**Symptom** 192 193Custom components A and B need to deliver the following effects: When custom component A, displayed at the bottom of the screen by default, is touched, it is hidden, and custom component B slides in from the bottom; when custom component B is touched, it is hidden, and custom component A slides in from the bottom. 194 195**Solution** 196 197You can use the **transition** attribute to create component transition animations. Set the **type** parameter to specify the component transition type, which can be component addition, component deletion, or both. Set the **translate** parameter to specify the translation of the component during transition. **NOTE**<br>The **transition** attribute must work with **animateTo**. The animation duration, curve, and delay follow the settings in **animateTo**. 198 199**Example** 200 201``` 202@Entry 203@Component 204struct ComponentTransition { 205 @State flag: boolean = true; 206 207 build() { 208 Stack({alignContent: Alignment.Bottom}) { 209 if (this.flag) { 210 ComponentChild1({ flag: $flag }) 211 .transition({ type: TransitionType.Insert,translate: { x: 0, y: 200 } }) 212 } 213 if (!this.flag) { 214 ComponentChild2({ flag: $flag }) 215 .transition({ type: TransitionType.Insert, translate: { x: 0, y: 200 } }) 216 } 217 }.height('100%').width('100%') 218 } 219} 220 221@Component 222struct ComponentChild1 { 223 @Link flag: boolean 224 225 build() { 226 Column() { 227 Image($r('app.media.ic_banner01')) 228 .width('100%') 229 .height(200) 230 .onClick(() => { 231 animateTo({ duration: 1000 }, () => { 232 this.flag = !this.flag; 233 }) 234 }) 235 } 236 } 237} 238 239@Component 240struct ComponentChild2 { 241 @Link flag: boolean 242 243 build() { 244 Column() { 245 Image($r('app.media.ic_banner02')) 246 .width('100%') 247 .height(200) 248 .onClick(() => { 249 animateTo({ duration: 1000 }, () => { 250 this.flag = !this.flag; 251 }) 252 }) 253 } 254 } 255} 256``` 257 258**Reference** 259 260[Enter/Exit Transition](../ui/arkts-enter-exit-transition.md) 261 262 263## What should I do if the Files application does not respond to touches? (API version 10) 264 265**Symptom** 266 267When the Files application icon is touched and held for 200 ms to 500 ms, the application does not respond. 268 269**Cause Analysis** 270 271An error occurs with the drag gesture recognition logic. As a result, when the application icon is touched and held for a specific period of time, the gesture recognizer enters the pending state and stops responding. 272 273**Solution** 274 275Long press the Files application icon or a blank area. 276 277## How do I customize event transfer between parent and child components? (API version 10) 278 279**Solution** 280 2811. When processing a touch event, the system conducts hit testing - from the parent component to its children - to determine the component that needs to respond to the event. Subsequent gesture recognition and competition are performed based on the test result. 282 2832. You can set the **hitTestBehavior** attribute to specify how a component behaves during hit testing. 284 2853. Intervention on gesture recognition and competition results may be refined with custom events and custom gesture judgment. 286 287**Reference** 288 2891. [Hit Test Control](../reference/apis-arkui/arkui-ts/ts-universal-attributes-hit-test-behavior.md) 290 2912. [Custom Event Dispatch](../reference/apis-arkui/arkui-ts/ts-universal-attributes-on-child-touch-test.md) 292 2933.[Custom Gesture Judgment](../reference/apis-arkui/arkui-ts/ts-gesture-customize-judge.md) 294 295## How do I enable a list to automatically rearrange the layout after one of the list items is dragged? (API version 10) 296 297**Solution** 298 2991. Configure the list or list items to be draggable, and register the **onDragStart** callback. 300 3012. Set **visibility** of the dragged item to **HIDDEN** in the **onDragStart** callback. 302 3032. Register the **onDragMove** callback on the list or list item to listen for the movement during dragging. 304 3053. During the dragging, use the **event** parameter of **onDragMove** to obtain the coordinates of the drag points. 306 3074. Calculate the distance between the drag point coordinates and the item middle line. When the drag point and middle line overlap, enable the space filling animation. 308 3095. Use the **componentUtils** API to obtain the item layout information. 310 3116. The space filling animation uses **animateTo** to change the index in the data source and trigger the list sorting animation. 312 3137. The drop animation can be customized. 314 315 **Example** 316 317```ts 318// Record the dragged item when the dragging is started. 319 .onDragStart((event?: DragEvent, extraParams?: string) => { 320 this.dragIndex = Number(item.data) 321 this.dragItem = item 322 }) 323 // Execute the space filling animation when the dragged item enters a valid drop target. 324 .onDragEnter((event?: DragEvent, extraParams?: string) => { 325 if (Number(item.data) != this.dragIndex) { 326 let current = this.dataSource.findIndex((element) => element.data === this.dragItem.data) 327 let index = this.dataSource.findIndex((element) => element.data === item.data) 328 animateTo({ 329 curve: curves.interpolatingSpring(0, 1, 400, 38) 330 }, () => { 331 this.dataSource.splice(current, 1) 332 this.dataSource.splice(index, 0, this.dragItem) 333 }) 334 } 335 }) 336 // Implement a custom drop animation on the dragged item when it is dropped on a valid drop target. 337 .onDrop((dragEvent: DragEvent) => { 338 dragEvent.useCustomDropAnimation = true; 339 // Obtain the drop target. 340 let downLocation = getInspectorByKey(item.data) 341 let currentLocation = dragEvent.getPreviewRect() 342 this.dragItem.scale = 1.05 343 animateTo({ 344 curve: curves.interpolatingSpring(14, 1, 170, 17) 345 }, () => { 346 this.dragItem.scale = 1 347 }) 348 }) 349``` 350