• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Keyboard and Mouse Event
2
3
4Keyboard and mouse events refer to the input events of the peripheral keyboard and mouse.
5
6
7## Mouse Event
8
9The supported mouse events include the events triggered by the peripheral mouse and touchpad.
10
11Mouse events can trigger the following callbacks.
12
13| Name                                      | Description                                      |
14| ---------------------------------------- | ---------------------------------------- |
15| onHover(event:&nbsp;(isHover:&nbsp;boolean)&nbsp;=&gt;&nbsp;void) | Triggered when the mouse cursor enters or leaves the component.<br>**isHover**: whether the mouse cursor hovers over the component. The value **true** means that the mouse cursor enters the component, and the value **false** means that the mouse cursor leaves the component.|
16| onMouse(event:&nbsp;(event?:&nbsp;MouseEvent)&nbsp;=&gt;&nbsp;void) | Triggered when the component is clicked by a mouse button or the mouse cursor moves on the component. The **event** parameter indicates the timestamp, mouse button, action, coordinates of the clicked point on the entire screen, and coordinates of the clicked point relative to the component when the event is triggered.|
17
18When the component is bound to the **onHover** callback, you can use the [hoverEffect](../reference/arkui-ts/ts-universal-attributes-hover-effect.md) attribute to set the hover effect of the component in hover state.
19
20
21  **Figure 1** Mouse event data flow
22
23
24![en-us_image_0000001511900504](figures/en-us_image_0000001511900504.png)
25
26
27When ArkUI receives the mouse event, it checks whether the mouse event concerns pressing, lifting, or moving of the left mouse button, and then responds accordingly.
28
29
30- Yes: The mouse event is first converted into a touch event in the same position, and a collision test, gesture judgment, and callback response of the touch event are performed. The collision test and callback response of the mouse event are then performed.
31
32- No: Only the collision test and callback response of the mouse event are performed.
33
34
35>**NOTE**
36>
37>All touch events and gesture events that can be responded to by a single finger may be operated and responded by using the left mouse button. For example, to implement page redirection invoked by clicking a button with support for finger touches and left-clicks, you just need to bind one click event (**onClick**). If you want to implement different effects for the finger touch and the left-click, you can use the **source** parameter in the **onClick** callback to determine whether the current event is triggered by a finger or a mouse.
38
39
40### onHover
41
42
43```ts
44onHover(event: (isHover?: boolean) => void)
45```
46
47
48Triggered when the mouse cursor enters or leaves the component. The **isHover** parameter indicates whether the mouse cursor hovers over the component. This event does not support custom bubbling settings. By default, event bubbling occurs between parent and child components.
49
50
51If this API is bound to a component, it is triggered when the mouse cursor enters the component from outside and the value of **isHover** is **true**, or when the mouse cursor leaves the component and the value of **isHover** is **false**.
52
53
54>**NOTE**
55>
56>Event bubbling is an event propagation in the document object model (DOM) when an event is first handled by an element and then bubbles up to its parent element.
57
58
59
60
61```ts
62// xxx.ets
63@Entry
64@Component
65struct MouseExample {
66  @State isHovered: boolean = false;
67
68  build() {
69    Column() {
70      Button(this.isHovered ? 'Hovered!' : 'Not Hover')
71        .width(200).height(100)
72        .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
73        .onHover((isHover: boolean) => { // Use the onHover API to listen for whether the mouse cursor is hovered over the component.
74          this.isHovered = isHover;
75        })
76    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
77  }
78}
79```
80
81
82In this example, a **\<Button component>** is created, with the initial background color of gray and the content of **Not Hover**. The component is bound to the **onHover** callback. In the callback, **this.isHovered** is set to the callback parameter **isHover**.
83
84
85When the cursor moves from outside the button to inside the button, the callback is invoked, the value of **isHover** changes to **true**, the value of **isHovered** changes to **true**, the background color of the component changes to **Color.Green**, and the content changes to **Hovered!**.
86
87
88When the cursor moves from inside the button to outside the button, the callback is invoked, the value of **isHover** changes to **false**, and the component restores to its initial style.
89
90
91![onHover](figures/onHover.gif)
92
93
94### onMouse
95
96
97```ts
98onMouse(event: (event?: MouseEvent) => void)
99```
100
101
102Triggered when a mouse event occurs. It is triggered each time an action by the mouse cursor (**MouseAction**) is detected in the component. The parameter is a [MouseEvent](../reference/arkui-ts/ts-universal-mouse-key.md) object, which indicates the mouse event that triggers the callback. This event supports custom bubbling settings. By default, event bubbling occurs between parent and child components. It is commonly used for customized mouse behavior logic processing.
103
104
105You can use the **MouseEvent** object in the callback to obtain information about the triggered event, including the coordinates (**screenX**/**screenY**/**x**/**y**), button ([MouseButton](../reference/arkui-ts/ts-appendix-enums.md#mousebutton)), action ([MouseAction](../reference/arkui-ts/ts-appendix-enums.md#mouseaction)), timestamp (**timestamp**), display area of the object that triggers the event ([EventTarget](../reference/arkui-ts/ts-universal-events-click.md)), and event source ([SourceType](../reference/arkui-ts/ts-gesture-settings.md)). The **stopPropagation** callback of **MouseEvent** is used to set whether the current event blocks bubbling.
106
107
108>**NOTE**
109>
110>**MouseButton** indicates the physical mouse button being pressed or released that triggers the mouse event. The values are **Left**, **Right**, **Middle**, **Back**, **Forward**, and **None**. **None** indicates that no button is pressed or released, which means that the event is triggered by the mouse cursor moving on the component.
111
112
113
114```ts
115// xxx.ets
116@Entry
117@Component
118struct MouseExample {
119  @State isHovered: boolean = false;
120  @State buttonText: string = '';
121  @State columnText: string = '';
122
123  build() {
124    Column() {
125      Button(this.isHovered ? 'Hovered!' : 'Not Hover')
126        .width(200)
127        .height(100)
128        .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
129        .onHover((isHover: boolean) => {
130          this.isHovered = isHover
131        })
132        .onMouse((event: MouseEvent) => {    // Set the onMouse callback for the button.
133          this.buttonText = 'Button onMouse:\n' + '' +
134          'button = ' + event.button + '\n' +
135          'action = ' + event.action + '\n' +
136          'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
137          'screenXY=(' + event.screenX + ',' + event.screenY + ')';
138        })
139      Divider()
140      Text(this.buttonText).fontColor(Color.Green)
141      Divider()
142      Text(this.columnText).fontColor(Color.Red)
143    }
144    .width('100%')
145    .height('100%')
146    .justifyContent(FlexAlign.Center)
147    .borderWidth(2)
148    .borderColor(Color.Red)
149    .onMouse((event: MouseEvent) => {    // Set the onMouse callback for the column.
150      this.columnText = 'Column onMouse:\n' + '' +
151      'button = ' + event.button + '\n' +
152      'action = ' + event.action + '\n' +
153      'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
154      'screenXY=(' + event.screenX + ',' + event.screenY + ')';
155    })
156  }
157}
158```
159
160
161Bind the **onMouse** API to the button based on the **onHover** example. In the callback, the values of the callback parameters, such as **button** and **action**, are displayed. The same settings are performed on the outer **\<Column>** container. The entire process can be divided into the following two actions:
162
163
1641. Moving the mouse cursor: When the mouse cursor is moved from outside the button to inside the button, only the **onMouse** callback of the **\<Column>** is triggered. When the mouse cursor is moved to the button, as the **onMouse** event bubbles up by default, both the **onMouse** callbacks of the **\<Column>** and **\<Button>** components are invoked. In this process, the mouse cursor moves, but no mouse button is clicked. Therefore, in the displayed information, the value of **button** is 0 (enumerated value of **MouseButton.None**) and the value of **action** is **3** (enumerated value of **MouseAction.Move**).
165
1662. Clicking the mouse button: After the mouse cursor enters the **\<Button>** component, the **\<Button>** component is clicked twice, namely, left-click and right-click.
167   Left-clicked: button = 1 (enumerated value of **MouseButton.Left**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**).
168
169   Right-click: button = 2 (enumerated value of **MouseButton.Right**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**)
170
171
172![onMouse1](figures/onMouse1.gif)
173
174
175To prevent the mouse event from bubbling, call the **stopPropagation()** API.
176
177
178
179```ts
180Button(this.isHovered ? 'Hovered!' : 'Not Hover')
181  .width(200)
182  .height(100)
183  .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
184  .onHover((isHover: boolean) => {
185    this.isHovered = isHover;
186  })
187  .onMouse((event: MouseEvent) => {
188    event.stopPropagation(); // Prevent the mouse event from bubbling.
189    this.buttonText = 'Button onMouse:\n' + '' +
190    'button = ' + event.button + '\n' +
191    'action = ' + event.action + '\n' +
192    'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
193    'screenXY=(' + event.screenX + ',' + event.screenY + ')';
194  })
195```
196
197
198To prevent the mouse event of the child component (**\<Button>**) from bubbling up to its parent component (**\<Column>**), use the **event** parameter in the **onMouse** callback of **\<Button>** to call the **stopPropagation** API.
199
200
201
202```ts
203event.stopPropagation()
204```
205
206
207With bubbling prevented, the mouse event on the **\<Button>** component will trigger the **onMouse** callback of the **\<Button>** component, but not the **onMouse** callback of the **\<Column>** component.
208
209
210### hoverEffect
211
212
213```ts
214hoverEffect(value: HoverEffect)
215```
216
217
218Sets the hover effect of the component in hover state. The parameter value type is **HoverEffect**. The **Auto**, **Scale**, and **Highlight** effects are preset and do not support customization.
219
220
221  **Table 1** HoverEffect
222
223| Enum| Description                                    |
224| -------------- | ---------------------------------------- |
225| Auto           | Default hover effect, which varies by component.                    |
226| Scale          | Scale effect. When the mouse cursor is placed over the component, the component is scaled up from 100% to 105%. When the mouse cursor is moved away, the component is scaled down from 105% to 100%.|
227| Highlight      | Background fade-in and fade-out effect. When the mouse cursor is placed over the component, a white layer with 5% opacity is applied to the background color of the component, resulting in a dimmed background. When the mouse cursor is moved away, the background color of the component is restored to the original style.|
228| None           | No effect.                                 |
229
230
231
232```ts
233// xxx.ets
234@Entry
235@Component
236struct HoverExample {
237  build() {
238    Column({ space: 10 }) {
239      Button('Auto')
240        .width(170).height(70)
241      Button('Scale')
242        .width(170).height(70)
243        .hoverEffect(HoverEffect.Scale)
244      Button('Highlight')
245        .width(170).height(70)
246        .hoverEffect(HoverEffect.Highlight)
247      Button('None')
248        .width(170).height(70)
249        .hoverEffect(HoverEffect.None)
250    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
251  }
252}
253```
254
255
256![hoverEffect](figures/hoverEffect.gif)
257
258
259For the **\<Button>** component, **Auto** creates the same effect as **Scale**.
260
261
262## Key Event
263
264  **Figure 2** Key event data flow
265
266![en-us_image_0000001511580944](figures/en-us_image_0000001511580944.png)
267
268
269The key event is triggered by a device such as a peripheral keyboard, and is sent to the currently focused window after being converted by the driver and multi-mode processing. After obtaining the event, the window distributes the event to the input method (which consumes the key as the input). If the input method does not consume the key event, the window sends the event to the ArkUI framework. Therefore, when an input box component has focus and an input method is enabled, most key events are consumed by the input method. For example, a letter key is used by the input method to enter a letter in the input box, and an arrow key is used by the input method to switch to the desired candidate word.
270
271
272After the key event is sent to the ArkUI framework, it first identifies the complete focus chain, and then sends the key event one by one from the leaf node to the root node.
273
274
275### onKeyEvent
276
277
278```ts
279onKeyEvent(event: (event?: KeyEvent) => void)
280```
281
282
283Triggered when the bound component has [focus](arkts-common-events-focus-event.md) and a key event occurs on the component. The callback parameter [KeyEvent](../reference/arkui-ts/ts-universal-events-key.md) can be used to obtain the information about the key event, including [KeyType](../reference/arkui-ts/ts-appendix-enums.md#keytype), [keyCode](../reference/apis/js-apis-keycode.md), keyText, [KeySource](../reference/arkui-ts/ts-appendix-enums.md#keysource), **deviceId**, **metaKey**, **timestamp**, and **stopPropagation**.
284
285
286
287```ts
288// xxx.ets
289@Entry
290@Component
291struct KeyEventExample {
292  @State buttonText: string = '';
293  @State buttonType: string = '';
294  @State columnText: string = '';
295  @State columnType: string = '';
296
297  build() {
298    Column() {
299      Button('onKeyEvent')
300        .width(140).height(70)
301        .onKeyEvent((event: KeyEvent) => {// Set the onKeyEvent event for the <Button> component.
302          if (event.type === KeyType.Down) {
303            this.buttonType = 'Down';
304          }
305          if (event.type === KeyType.Up) {
306            this.buttonType = 'Up';
307          }
308          this.buttonText = 'Button: \n' +
309          'KeyType:' + this.buttonType + '\n' +
310          'KeyCode:' + event.keyCode + '\n' +
311          'KeyText:' + event.keyText;
312        })
313
314      Divider()
315      Text(this.buttonText).fontColor(Color.Green)
316
317      Divider()
318      Text(this.columnText).fontColor(Color.Red)
319    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
320    .onKeyEvent((event: KeyEvent) => {// Set the onKeyEvent event for the parent container <Column>.
321      if (event.type === KeyType.Down) {
322        this.columnType = 'Down';
323      }
324      if (event.type === KeyType.Up) {
325        this.columnType = 'Up';
326      }
327      this.columnText = 'Column: \n' +
328      'KeyType:' + this.buttonType + '\n' +
329      'KeyCode:' + event.keyCode + '\n' +
330      'KeyText:' + event.keyText;
331    })
332  }
333}
334```
335
336
337In the preceding example, **onKeyEvent** is bound to the **\<Button>** component and its parent container **\<Column>**. After the application opens and loads a page, the first focusable non-container component in the component tree automatically obtains focus. As the application has only one **\<Button>** component, the component automatically obtains focus. Because the **\<Button>** component is a child node of the **\<Column>** component, the **\<Column>** component also obtains focus. For details about the focus obtaining mechanism, see [Focus Event](arkts-common-events-focus-event.md).
338
339
340![en-us_image_0000001511421324](figures/en-us_image_0000001511421324.gif)
341
342
343After the application is opened, press the following keys in sequence: Space, Enter, Left Ctrl, Left Shift, Letter A, and Letter Z.
344
345
3461. Because the **onKeyEvent** event bubbles by default, the **onKeyEvent** callbacks of both **\<Button>** and **\<Column>** are invoked.
347
3482. Each key has two callbacks, which correspond to **KeyType.Down** and **KeyType.Up** respectively, indicating that the key is pressed and then lifted.
349
350
351To prevent the key event of the **\<Button>** component from bubbling up to its parent container **\<Column>**, add the **event.stopPropagation()** API to the **onKeyEvent** callback of **\<Button>**.
352
353
354
355```ts
356Button('onKeyEvent')
357  .width(140).height(70)
358  .onKeyEvent((event: KeyEvent) => {
359    // Use stopPropagation to prevent the key event from bubbling up.
360    event.stopPropagation();
361    if (event.type === KeyType.Down) {
362      this.buttonType = 'Down';
363    }
364    if (event.type === KeyType.Up) {
365       this.buttonType = 'Up';
366    }
367     this.buttonText = 'Button: \n' +
368     'KeyType:' + this.buttonType + '\n' +
369     'KeyCode:' + event.keyCode + '\n' +
370     'KeyText:' + event.keyText;
371})
372```
373
374
375![en-us_image_0000001511900508](figures/en-us_image_0000001511900508.gif)
376