1e41f4b71Sopenharmony_ci# Keyboard and Mouse Event
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciKeyboard and mouse events refer to the input events of the peripheral keyboard and mouse.
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci
7e41f4b71Sopenharmony_ci## Mouse Event
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ciThe supported mouse events include the events triggered by the peripheral mouse and touchpad.
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ciMouse events can trigger the following callbacks.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci| Name                                      | Description                                      |
14e41f4b71Sopenharmony_ci| ---------------------------------------- | ---------------------------------------- |
15e41f4b71Sopenharmony_ci| onHover(event: (isHover: boolean) =&gt; void) | Triggered when the mouse pointer enters or leaves the component.<br>**isHover**: whether the mouse pointer hovers over the component. The value **true** means that the mouse pointer enters the component, and the value **false** means that the mouse pointer leaves the component.|
16e41f4b71Sopenharmony_ci| onMouse(event: (event?: MouseEvent) =&gt; void) | Triggered when the component is clicked by a mouse button or the mouse pointer 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.|
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ciWhen the component is bound to the **onHover** callback, you can use the [hoverEffect](../reference/apis-arkui/arkui-ts/ts-universal-attributes-hover-effect.md#hovereffect) attribute to set the hover effect of the component in hover state.
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ci
21e41f4b71Sopenharmony_ci  **Figure 1** Mouse event data flow 
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci![en-us_image_0000001511900504](figures/en-us_image_0000001511900504.png)
25e41f4b71Sopenharmony_ci
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ciWhen 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.
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci
30e41f4b71Sopenharmony_ci- 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.
31e41f4b71Sopenharmony_ci
32e41f4b71Sopenharmony_ci- No: Only the collision test and callback response of the mouse event are performed.
33e41f4b71Sopenharmony_ci
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci>**NOTE**
36e41f4b71Sopenharmony_ci>
37e41f4b71Sopenharmony_ci>All touch events and gesture events that can be responded to by a single finger may be triggered and responded to 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.
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci
40e41f4b71Sopenharmony_ci### onHover
41e41f4b71Sopenharmony_ci
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci```ts
44e41f4b71Sopenharmony_cionHover(event: (isHover: boolean) => void)
45e41f4b71Sopenharmony_ci```
46e41f4b71Sopenharmony_ci
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ciTriggered when the mouse pointer enters or leaves the component. The **isHover** parameter indicates whether the mouse pointer hovers over the component. This event does not support custom bubbling settings. By default, event bubbling occurs between parent and child components.
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci
51e41f4b71Sopenharmony_ciIf this API is bound to a component, it is triggered when the mouse pointer enters the component from outside and the value of **isHover** is **true**, or when the mouse pointer leaves the component and the value of **isHover** is **false**.
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci
54e41f4b71Sopenharmony_ci>**NOTE**
55e41f4b71Sopenharmony_ci>
56e41f4b71Sopenharmony_ci>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.
57e41f4b71Sopenharmony_ci
58e41f4b71Sopenharmony_ci
59e41f4b71Sopenharmony_ci
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ci```ts
62e41f4b71Sopenharmony_ci// xxx.ets
63e41f4b71Sopenharmony_ci@Entry
64e41f4b71Sopenharmony_ci@Component
65e41f4b71Sopenharmony_cistruct MouseExample {
66e41f4b71Sopenharmony_ci  @State hoverText: string = 'Not Hover';
67e41f4b71Sopenharmony_ci  @State Color: Color = Color.Gray;
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci  build() {
70e41f4b71Sopenharmony_ci    Column() {
71e41f4b71Sopenharmony_ci      Button(this.hoverText)
72e41f4b71Sopenharmony_ci        .width(200).height(100)
73e41f4b71Sopenharmony_ci        .backgroundColor(this.Color)
74e41f4b71Sopenharmony_ci        .onHover((isHover?: boolean) => { // Use the onHover API to listen for whether the mouse cursor is hovered over the button.
75e41f4b71Sopenharmony_ci          if (isHover) {
76e41f4b71Sopenharmony_ci            this.hoverText = 'Hovered!';
77e41f4b71Sopenharmony_ci            this.Color = Color.Green;
78e41f4b71Sopenharmony_ci          }
79e41f4b71Sopenharmony_ci          else {
80e41f4b71Sopenharmony_ci            this.hoverText = 'Not Hover';
81e41f4b71Sopenharmony_ci            this.Color = Color.Gray;
82e41f4b71Sopenharmony_ci          }
83e41f4b71Sopenharmony_ci        })
84e41f4b71Sopenharmony_ci    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
85e41f4b71Sopenharmony_ci  }
86e41f4b71Sopenharmony_ci}
87e41f4b71Sopenharmony_ci```
88e41f4b71Sopenharmony_ci
89e41f4b71Sopenharmony_ci
90e41f4b71Sopenharmony_ciIn 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**.
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ciWhen the mouse pointer 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!**.
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ciWhen the mouse pointer 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.
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci![onHover](figures/onHover.gif)
100e41f4b71Sopenharmony_ci
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ci### onMouse
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ci```ts
106e41f4b71Sopenharmony_cionMouse(event: (event?: MouseEvent) => void)
107e41f4b71Sopenharmony_ci```
108e41f4b71Sopenharmony_ci
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ciTriggered when a mouse event occurs. It is triggered each time a mouse pointer action (**MouseAction**) is detected in the component. The parameter is a [MouseEvent](../reference/apis-arkui/arkui-ts/ts-universal-mouse-key.md#mouseevent) 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.
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci
113e41f4b71Sopenharmony_ciYou can use the **MouseEvent** object in the callback to obtain information about the triggered event, including the coordinates (**displayX**, **displayY**, **windowX**, **windowY**, **x**, and **y**), button ([MouseButton](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#mousebutton)), action ([MouseAction](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#mouseaction)), timestamp (**timestamp**), display area of the object that triggers the event ([EventTarget](../reference/apis-arkui/arkui-ts/ts-universal-events-click.md#eventtarget8)), and event source ([SourceType](../reference/apis-arkui/arkui-ts/ts-gesture-settings.md#sourcetype)). The **stopPropagation** callback of **MouseEvent** is used to set whether the current event blocks bubbling.
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ci
116e41f4b71Sopenharmony_ci>**NOTE**
117e41f4b71Sopenharmony_ci>
118e41f4b71Sopenharmony_ci>**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 pointer moving on the component.
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci```ts
123e41f4b71Sopenharmony_ci// xxx.ets
124e41f4b71Sopenharmony_ci@Entry
125e41f4b71Sopenharmony_ci@Component
126e41f4b71Sopenharmony_cistruct MouseExample {
127e41f4b71Sopenharmony_ci  @State buttonText: string = '';
128e41f4b71Sopenharmony_ci  @State columnText: string = '';
129e41f4b71Sopenharmony_ci  @State hoverText: string = 'Not Hover';
130e41f4b71Sopenharmony_ci  @State Color: Color = Color.Gray;
131e41f4b71Sopenharmony_ci
132e41f4b71Sopenharmony_ci  build() {
133e41f4b71Sopenharmony_ci    Column() {
134e41f4b71Sopenharmony_ci      Button(this.hoverText)
135e41f4b71Sopenharmony_ci        .width(200)
136e41f4b71Sopenharmony_ci        .height(100)
137e41f4b71Sopenharmony_ci        .backgroundColor(this.Color)
138e41f4b71Sopenharmony_ci        .onHover((isHover?: boolean) => {
139e41f4b71Sopenharmony_ci          if (isHover) {
140e41f4b71Sopenharmony_ci            this.hoverText = 'Hovered!';
141e41f4b71Sopenharmony_ci            this.Color = Color.Green;
142e41f4b71Sopenharmony_ci          }
143e41f4b71Sopenharmony_ci          else {
144e41f4b71Sopenharmony_ci            this.hoverText = 'Not Hover';
145e41f4b71Sopenharmony_ci            this.Color = Color.Gray;
146e41f4b71Sopenharmony_ci          }
147e41f4b71Sopenharmony_ci        })
148e41f4b71Sopenharmony_ci        .onMouse((event?: MouseEvent) => { // Set the onMouse callback for the button.
149e41f4b71Sopenharmony_ci          if (event) {
150e41f4b71Sopenharmony_ci            this.buttonText = 'Button onMouse:\n' + '' +
151e41f4b71Sopenharmony_ci              'button = ' + event.button + '\n' +
152e41f4b71Sopenharmony_ci              'action = ' + event.action + '\n' +
153e41f4b71Sopenharmony_ci              'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
154e41f4b71Sopenharmony_ci              'windowXY=(' + event.windowX + ',' + event.windowY + ')';
155e41f4b71Sopenharmony_ci          }
156e41f4b71Sopenharmony_ci        })
157e41f4b71Sopenharmony_ci      Divider()
158e41f4b71Sopenharmony_ci      Text(this.buttonText).fontColor(Color.Green)
159e41f4b71Sopenharmony_ci      Divider()
160e41f4b71Sopenharmony_ci      Text(this.columnText).fontColor(Color.Red)
161e41f4b71Sopenharmony_ci    }
162e41f4b71Sopenharmony_ci    .width('100%')
163e41f4b71Sopenharmony_ci    .height('100%')
164e41f4b71Sopenharmony_ci    .justifyContent(FlexAlign.Center)
165e41f4b71Sopenharmony_ci    .borderWidth(2)
166e41f4b71Sopenharmony_ci    .borderColor(Color.Red)
167e41f4b71Sopenharmony_ci    .onMouse((event?: MouseEvent) => { // Set the onMouse callback for the column.
168e41f4b71Sopenharmony_ci      if (event) {
169e41f4b71Sopenharmony_ci        this.columnText = 'Column onMouse:\n' + '' +
170e41f4b71Sopenharmony_ci          'button = ' + event.button + '\n' +
171e41f4b71Sopenharmony_ci          'action = ' + event.action + '\n' +
172e41f4b71Sopenharmony_ci          'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
173e41f4b71Sopenharmony_ci          'windowXY=(' + event.windowX + ',' + event.windowY + ')';
174e41f4b71Sopenharmony_ci      }
175e41f4b71Sopenharmony_ci    })
176e41f4b71Sopenharmony_ci  }
177e41f4b71Sopenharmony_ci}
178e41f4b71Sopenharmony_ci```
179e41f4b71Sopenharmony_ci
180e41f4b71Sopenharmony_ci
181e41f4b71Sopenharmony_ciBind 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:
182e41f4b71Sopenharmony_ci
183e41f4b71Sopenharmony_ci
184e41f4b71Sopenharmony_ci1. Moving the mouse pointer: When the mouse pointer is moved from outside the button to inside the button, only the **onMouse** callback of the **Column** is triggered. When the mouse pointer 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 pointer 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**).
185e41f4b71Sopenharmony_ci
186e41f4b71Sopenharmony_ci2. Clicking the mouse button: After the mouse pointer enters the **Button** component, the **Button** component is clicked twice, namely, left-click and right-click.
187e41f4b71Sopenharmony_ci   Left-clicked: button = 1 (enumerated value of **MouseButton.Left**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**).
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_ci   Right-click: button = 2 (enumerated value of **MouseButton.Right**); action = 1 (enumerated value of **MouseAction.Press**); action = 2 (enumerated value of **MouseAction.Release**)
190e41f4b71Sopenharmony_ci
191e41f4b71Sopenharmony_ci
192e41f4b71Sopenharmony_ci![onMouse1](figures/onMouse1.gif)
193e41f4b71Sopenharmony_ci
194e41f4b71Sopenharmony_ci
195e41f4b71Sopenharmony_ciTo prevent the mouse event from bubbling, call the **stopPropagation()** API.
196e41f4b71Sopenharmony_ci
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci
199e41f4b71Sopenharmony_ci```ts
200e41f4b71Sopenharmony_ciclass ish{
201e41f4b71Sopenharmony_ci  isHovered:boolean = false
202e41f4b71Sopenharmony_ci  set(val:boolean){
203e41f4b71Sopenharmony_ci    this.isHovered = val;
204e41f4b71Sopenharmony_ci  }
205e41f4b71Sopenharmony_ci}
206e41f4b71Sopenharmony_ciclass butf{
207e41f4b71Sopenharmony_ci  buttonText:string = ''
208e41f4b71Sopenharmony_ci  set(val:string){
209e41f4b71Sopenharmony_ci    this.buttonText = val
210e41f4b71Sopenharmony_ci  }
211e41f4b71Sopenharmony_ci}
212e41f4b71Sopenharmony_ci@Entry
213e41f4b71Sopenharmony_ci@Component
214e41f4b71Sopenharmony_cistruct MouseExample {
215e41f4b71Sopenharmony_ci  @State isHovered:ish = new ish()
216e41f4b71Sopenharmony_ci  build(){
217e41f4b71Sopenharmony_ci    Column(){
218e41f4b71Sopenharmony_ci      Button(this.isHovered ? 'Hovered!' : 'Not Hover')
219e41f4b71Sopenharmony_ci        .width(200)
220e41f4b71Sopenharmony_ci        .height(100)
221e41f4b71Sopenharmony_ci        .backgroundColor(this.isHovered ? Color.Green : Color.Gray)
222e41f4b71Sopenharmony_ci        .onHover((isHover?: boolean) => {
223e41f4b71Sopenharmony_ci          if(isHover) {
224e41f4b71Sopenharmony_ci            let ishset = new ish()
225e41f4b71Sopenharmony_ci            ishset.set(isHover)
226e41f4b71Sopenharmony_ci          }
227e41f4b71Sopenharmony_ci        })
228e41f4b71Sopenharmony_ci        .onMouse((event?: MouseEvent) => {
229e41f4b71Sopenharmony_ci          if (event) {
230e41f4b71Sopenharmony_ci            if (event.stopPropagation) {
231e41f4b71Sopenharmony_ci              event.stopPropagation(); // Prevent the onMouse event from bubbling.
232e41f4b71Sopenharmony_ci            }
233e41f4b71Sopenharmony_ci            let butset = new butf()
234e41f4b71Sopenharmony_ci            butset.set('Button onMouse:\n' + '' +
235e41f4b71Sopenharmony_ci              'button = ' + event.button + '\n' +
236e41f4b71Sopenharmony_ci              'action = ' + event.action + '\n' +
237e41f4b71Sopenharmony_ci              'x,y = (' + event.x + ',' + event.y + ')' + '\n' +
238e41f4b71Sopenharmony_ci              'windowXY=(' + event.windowX + ',' + event.windowY + ')');
239e41f4b71Sopenharmony_ci          }
240e41f4b71Sopenharmony_ci        })
241e41f4b71Sopenharmony_ci    }
242e41f4b71Sopenharmony_ci  }
243e41f4b71Sopenharmony_ci}
244e41f4b71Sopenharmony_ci```
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci
247e41f4b71Sopenharmony_ciTo 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.
248e41f4b71Sopenharmony_ci
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci
251e41f4b71Sopenharmony_ci```ts
252e41f4b71Sopenharmony_cievent.stopPropagation()
253e41f4b71Sopenharmony_ci```
254e41f4b71Sopenharmony_ci
255e41f4b71Sopenharmony_ci
256e41f4b71Sopenharmony_ciWith 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.
257e41f4b71Sopenharmony_ci
258e41f4b71Sopenharmony_ci
259e41f4b71Sopenharmony_ci### hoverEffect
260e41f4b71Sopenharmony_ci
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ci```ts
263e41f4b71Sopenharmony_cihoverEffect(value: HoverEffect)
264e41f4b71Sopenharmony_ci```
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci
267e41f4b71Sopenharmony_ciSets 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.
268e41f4b71Sopenharmony_ci
269e41f4b71Sopenharmony_ci
270e41f4b71Sopenharmony_ci  **Table 1** HoverEffect
271e41f4b71Sopenharmony_ci
272e41f4b71Sopenharmony_ci| Value| Description                                    |
273e41f4b71Sopenharmony_ci| -------------- | ---------------------------------------- |
274e41f4b71Sopenharmony_ci| Auto           | Default hover effect, which varies by component.                    |
275e41f4b71Sopenharmony_ci| Scale          | Scale effect. When the mouse pointer is placed over the component, the component is scaled up from 100% to 105%. When the mouse pointer is moved away, the component is scaled down from 105% to 100%.|
276e41f4b71Sopenharmony_ci| Highlight      | Background fade-in and fade-out effect. When the mouse pointer 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 pointer is moved away, the background color of the component is restored to the original style.|
277e41f4b71Sopenharmony_ci| None           | No effect.                                 |
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci
280e41f4b71Sopenharmony_ci
281e41f4b71Sopenharmony_ci```ts
282e41f4b71Sopenharmony_ci// xxx.ets
283e41f4b71Sopenharmony_ci@Entry
284e41f4b71Sopenharmony_ci@Component
285e41f4b71Sopenharmony_cistruct HoverExample {
286e41f4b71Sopenharmony_ci  build() {
287e41f4b71Sopenharmony_ci    Column({ space: 10 }) {
288e41f4b71Sopenharmony_ci      Button('Auto')
289e41f4b71Sopenharmony_ci        .width(170).height(70)
290e41f4b71Sopenharmony_ci      Button('Scale')
291e41f4b71Sopenharmony_ci        .width(170).height(70)
292e41f4b71Sopenharmony_ci        .hoverEffect(HoverEffect.Scale)
293e41f4b71Sopenharmony_ci      Button('Highlight')
294e41f4b71Sopenharmony_ci        .width(170).height(70)
295e41f4b71Sopenharmony_ci        .hoverEffect(HoverEffect.Highlight)
296e41f4b71Sopenharmony_ci      Button('None')
297e41f4b71Sopenharmony_ci        .width(170).height(70)
298e41f4b71Sopenharmony_ci        .hoverEffect(HoverEffect.None)
299e41f4b71Sopenharmony_ci    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
300e41f4b71Sopenharmony_ci  }
301e41f4b71Sopenharmony_ci}
302e41f4b71Sopenharmony_ci```
303e41f4b71Sopenharmony_ci
304e41f4b71Sopenharmony_ci
305e41f4b71Sopenharmony_ci![hoverEffect](figures/hoverEffect.gif)
306e41f4b71Sopenharmony_ci
307e41f4b71Sopenharmony_ci
308e41f4b71Sopenharmony_ciThe default hover effect for the button is the **Highlight** effect. Therefore, the effects of **Auto** and **Highlight** are the same. The **Highlight** effect darkens the background color, **Scale** causes the component to scale, and **None** disables the hover effect.
309e41f4b71Sopenharmony_ci
310e41f4b71Sopenharmony_ci
311e41f4b71Sopenharmony_ci## Key Event
312e41f4b71Sopenharmony_ci
313e41f4b71Sopenharmony_ci### Key Event Data Flow
314e41f4b71Sopenharmony_ci
315e41f4b71Sopenharmony_ci![en-us_image_0000001511580944](figures/en-us_image_0000001511580944.png)
316e41f4b71Sopenharmony_ci
317e41f4b71Sopenharmony_ci
318e41f4b71Sopenharmony_ciAfter being triggered by a device such as a peripheral keyboard, a key event has its data processed and converted by the driver and multimodal input modules, and then is sent to the currently focused window. The window dispatches the received event, following the sequence below. The dispatch stops once the event is consumed.
319e41f4b71Sopenharmony_ci
320e41f4b71Sopenharmony_ci1. The window first dispatches the event to the ArkUI framework for invoking the **onKeyPreIme** callback bound to the component in focus as well as the page keyboard shortcuts.
321e41f4b71Sopenharmony_ci2. If the ArkUI framework does not consume the event, the window dispatches the event to the input method for key input.
322e41f4b71Sopenharmony_ci3. If the input method does not consume the event, the window dispatches the event to the ArkUI framework again for responding to the system default key event (for example, focus navigation) and for invoking the **onKeyEvent** callback bound to the component in focus.
323e41f4b71Sopenharmony_ci
324e41f4b71Sopenharmony_ciWhen a text box has focus and the 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 text box, and an arrow key is used by the input method to switch to the desired candidate word. Yet, if a keyboard shortcut is bound to the text box, the shortcut responds to the event first, and the event will not be consumed by the input method.
325e41f4b71Sopenharmony_ci
326e41f4b71Sopenharmony_ciAfter the key event is sent to the ArkUI framework, it first identifies the complete focus chain, and then sends the key event from one node to the next, following the leaf-to-root path.
327e41f4b71Sopenharmony_ci
328e41f4b71Sopenharmony_ciThe key event process for the **Web** component differs from the aforementioned process. The **Web** component does not match keyboard shortcuts when **onKeyPreIme** returns **false**. The unconsumed key event will be re-dispatched back to ArkUI through **ReDispatch** during the third key press dispatch. It is within this **ReDispatch** that operations such as matching keyboard shortcuts are performed again.
329e41f4b71Sopenharmony_ci
330e41f4b71Sopenharmony_ci### onKeyEvent & onKeyPreIme
331e41f4b71Sopenharmony_ci
332e41f4b71Sopenharmony_ci
333e41f4b71Sopenharmony_ci```ts
334e41f4b71Sopenharmony_cionKeyEvent(event: (event: KeyEvent) => void): T
335e41f4b71Sopenharmony_cionKeyPreIme(event: Callback<KeyEvent, boolean>): T
336e41f4b71Sopenharmony_ci```
337e41f4b71Sopenharmony_ci
338e41f4b71Sopenharmony_ci
339e41f4b71Sopenharmony_ciThe difference between the preceding two methods lies only in the triggering time. For details, see [Key Event Data Flow](#key-event-data-flow). The return value of **onKeyPreIme** determines whether the key event will be dispatched for the page keyboard shortcut, input method, and **onKeyEvent**.
340e41f4b71Sopenharmony_ci
341e41f4b71Sopenharmony_ci
342e41f4b71Sopenharmony_ciThe methods are triggered when the bound component has focus and a key event occurs on the component. The callback parameter [KeyEvent](../reference/apis-arkui/arkui-ts/ts-universal-events-key.md#keyevent) can be used to obtain the information about the key event, including [KeyType](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#keytype), [keyCode](../reference/apis-input-kit/js-apis-keycode.md#keycode), **keyText**, [KeySource](../reference/apis-arkui/arkui-ts/ts-appendix-enums.md#keysource), **deviceId**, **metaKey**, **timestamp**, and **stopPropagation**.
343e41f4b71Sopenharmony_ci
344e41f4b71Sopenharmony_ci
345e41f4b71Sopenharmony_ci
346e41f4b71Sopenharmony_ci```ts
347e41f4b71Sopenharmony_ci// xxx.ets
348e41f4b71Sopenharmony_ci@Entry
349e41f4b71Sopenharmony_ci@Component
350e41f4b71Sopenharmony_cistruct KeyEventExample {
351e41f4b71Sopenharmony_ci  @State buttonText: string = '';
352e41f4b71Sopenharmony_ci  @State buttonType: string = '';
353e41f4b71Sopenharmony_ci  @State columnText: string = '';
354e41f4b71Sopenharmony_ci  @State columnType: string = '';
355e41f4b71Sopenharmony_ci
356e41f4b71Sopenharmony_ci  build() {
357e41f4b71Sopenharmony_ci    Column() {
358e41f4b71Sopenharmony_ci      Button('onKeyEvent')
359e41f4b71Sopenharmony_ci        .defaultFocus(true)
360e41f4b71Sopenharmony_ci        .width(140).height(70)
361e41f4b71Sopenharmony_ci        .onKeyEvent((event?: KeyEvent) => { // Set the onKeyEvent event for the button.
362e41f4b71Sopenharmony_ci          if(event){
363e41f4b71Sopenharmony_ci            if (event.type === KeyType.Down) {
364e41f4b71Sopenharmony_ci              this.buttonType = 'Down';
365e41f4b71Sopenharmony_ci            }
366e41f4b71Sopenharmony_ci            if (event.type === KeyType.Up) {
367e41f4b71Sopenharmony_ci              this.buttonType = 'Up';
368e41f4b71Sopenharmony_ci            }
369e41f4b71Sopenharmony_ci            this.buttonText = 'Button: \n' +
370e41f4b71Sopenharmony_ci            'KeyType:' + this.buttonType + '\n' +
371e41f4b71Sopenharmony_ci            'KeyCode:' + event.keyCode + '\n' +
372e41f4b71Sopenharmony_ci            'KeyText:' + event.keyText;
373e41f4b71Sopenharmony_ci          }
374e41f4b71Sopenharmony_ci        })
375e41f4b71Sopenharmony_ci
376e41f4b71Sopenharmony_ci      Divider()
377e41f4b71Sopenharmony_ci      Text(this.buttonText).fontColor(Color.Green)
378e41f4b71Sopenharmony_ci
379e41f4b71Sopenharmony_ci      Divider()
380e41f4b71Sopenharmony_ci      Text(this.columnText).fontColor(Color.Red)
381e41f4b71Sopenharmony_ci    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
382e41f4b71Sopenharmony_ci    .onKeyEvent((event?: KeyEvent) => { // Set the onKeyEvent event for the parent container <Column>.
383e41f4b71Sopenharmony_ci      if(event){
384e41f4b71Sopenharmony_ci        if (event.type === KeyType.Down) {
385e41f4b71Sopenharmony_ci          this.columnType = 'Down';
386e41f4b71Sopenharmony_ci        }
387e41f4b71Sopenharmony_ci        if (event.type === KeyType.Up) {
388e41f4b71Sopenharmony_ci          this.columnType = 'Up';
389e41f4b71Sopenharmony_ci        }
390e41f4b71Sopenharmony_ci        this.columnText = 'Column: \n' +
391e41f4b71Sopenharmony_ci        'KeyType:' + this.buttonType + '\n' +
392e41f4b71Sopenharmony_ci        'KeyCode:' + event.keyCode + '\n' +
393e41f4b71Sopenharmony_ci        'KeyText:' + event.keyText;
394e41f4b71Sopenharmony_ci      }
395e41f4b71Sopenharmony_ci    })
396e41f4b71Sopenharmony_ci  }
397e41f4b71Sopenharmony_ci}
398e41f4b71Sopenharmony_ci```
399e41f4b71Sopenharmony_ci
400e41f4b71Sopenharmony_ci
401e41f4b71Sopenharmony_ciIn 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. Set the **Button** component as the default focus of the current page. 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).
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_ci
404e41f4b71Sopenharmony_ci![en-us_image_0000001511421324](figures/en-us_image_0000001511421324.gif)
405e41f4b71Sopenharmony_ci
406e41f4b71Sopenharmony_ci
407e41f4b71Sopenharmony_ciAfter the application is opened, press the following keys in sequence: Space, Enter, Left Ctrl, Left Shift, Letter A, and Letter Z.
408e41f4b71Sopenharmony_ci
409e41f4b71Sopenharmony_ci
410e41f4b71Sopenharmony_ci1. Because the **onKeyEvent** event bubbles by default, the **onKeyEvent** callbacks of both **Button** and **Column** are invoked.
411e41f4b71Sopenharmony_ci
412e41f4b71Sopenharmony_ci2. Each key has two callbacks, which correspond to **KeyType.Down** and **KeyType.Up** respectively, indicating that the key is pressed and then lifted.
413e41f4b71Sopenharmony_ci
414e41f4b71Sopenharmony_ci
415e41f4b71Sopenharmony_ciTo 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**.
416e41f4b71Sopenharmony_ci
417e41f4b71Sopenharmony_ci
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ci```ts
420e41f4b71Sopenharmony_ci@Entry
421e41f4b71Sopenharmony_ci@Component
422e41f4b71Sopenharmony_cistruct KeyEventExample {
423e41f4b71Sopenharmony_ci  @State buttonText: string = '';
424e41f4b71Sopenharmony_ci  @State buttonType: string = '';
425e41f4b71Sopenharmony_ci  @State columnText: string = '';
426e41f4b71Sopenharmony_ci  @State columnType: string = '';
427e41f4b71Sopenharmony_ci
428e41f4b71Sopenharmony_ci  build() {
429e41f4b71Sopenharmony_ci    Column() {
430e41f4b71Sopenharmony_ci      Button('onKeyEvent')
431e41f4b71Sopenharmony_ci        .defaultFocus(true)
432e41f4b71Sopenharmony_ci        .width(140).height(70)
433e41f4b71Sopenharmony_ci        .onKeyEvent((event?: KeyEvent) => {
434e41f4b71Sopenharmony_ci          // Use stopPropagation to prevent the key event from bubbling up.
435e41f4b71Sopenharmony_ci          if(event){
436e41f4b71Sopenharmony_ci            if(event.stopPropagation){
437e41f4b71Sopenharmony_ci              event.stopPropagation();
438e41f4b71Sopenharmony_ci            }
439e41f4b71Sopenharmony_ci            if (event.type === KeyType.Down) {
440e41f4b71Sopenharmony_ci              this.buttonType = 'Down';
441e41f4b71Sopenharmony_ci            }
442e41f4b71Sopenharmony_ci            if (event.type === KeyType.Up) {
443e41f4b71Sopenharmony_ci              this.buttonType = 'Up';
444e41f4b71Sopenharmony_ci            }
445e41f4b71Sopenharmony_ci            this.buttonText = 'Button: \n' +
446e41f4b71Sopenharmony_ci              'KeyType:' + this.buttonType + '\n' +
447e41f4b71Sopenharmony_ci              'KeyCode:' + event.keyCode + '\n' +
448e41f4b71Sopenharmony_ci              'KeyText:' + event.keyText;
449e41f4b71Sopenharmony_ci          }
450e41f4b71Sopenharmony_ci        })
451e41f4b71Sopenharmony_ci
452e41f4b71Sopenharmony_ci      Divider()
453e41f4b71Sopenharmony_ci      Text(this.buttonText).fontColor(Color.Green)
454e41f4b71Sopenharmony_ci
455e41f4b71Sopenharmony_ci      Divider()
456e41f4b71Sopenharmony_ci      Text(this.columnText).fontColor(Color.Red)
457e41f4b71Sopenharmony_ci    }.width('100%').height('100%').justifyContent(FlexAlign.Center)
458e41f4b71Sopenharmony_ci    .onKeyEvent((event?: KeyEvent) => { // Set the onKeyEvent event for the parent container <Column>.
459e41f4b71Sopenharmony_ci      if(event){
460e41f4b71Sopenharmony_ci        if (event.type === KeyType.Down) {
461e41f4b71Sopenharmony_ci          this.columnType = 'Down';
462e41f4b71Sopenharmony_ci        }
463e41f4b71Sopenharmony_ci        if (event.type === KeyType.Up) {
464e41f4b71Sopenharmony_ci          this.columnType = 'Up';
465e41f4b71Sopenharmony_ci        }
466e41f4b71Sopenharmony_ci        this.columnText = 'Column: \n' +
467e41f4b71Sopenharmony_ci          'KeyType:' + this.buttonType + '\n' +
468e41f4b71Sopenharmony_ci          'KeyCode:' + event.keyCode + '\n' +
469e41f4b71Sopenharmony_ci          'KeyText:' + event.keyText;
470e41f4b71Sopenharmony_ci      }
471e41f4b71Sopenharmony_ci    })
472e41f4b71Sopenharmony_ci  }
473e41f4b71Sopenharmony_ci}
474e41f4b71Sopenharmony_ci```
475e41f4b71Sopenharmony_ci
476e41f4b71Sopenharmony_ci
477e41f4b71Sopenharmony_ci![en-us_image_0000001511900508](figures/en-us_image_0000001511900508.gif)
478e41f4b71Sopenharmony_ci
479e41f4b71Sopenharmony_ciUse **OnKeyPreIme** to block the left arrow key input in the text box.
480e41f4b71Sopenharmony_ci```ts
481e41f4b71Sopenharmony_ciimport { KeyCode } from '@kit.InputKit';
482e41f4b71Sopenharmony_ci
483e41f4b71Sopenharmony_ci@Entry
484e41f4b71Sopenharmony_ci@Component
485e41f4b71Sopenharmony_cistruct PreImeEventExample {
486e41f4b71Sopenharmony_ci  @State buttonText: string = '';
487e41f4b71Sopenharmony_ci  @State buttonType: string = '';
488e41f4b71Sopenharmony_ci  @State columnText: string = '';
489e41f4b71Sopenharmony_ci  @State columnType: string = '';
490e41f4b71Sopenharmony_ci
491e41f4b71Sopenharmony_ci  build() {
492e41f4b71Sopenharmony_ci    Column() {
493e41f4b71Sopenharmony_ci      Search({
494e41f4b71Sopenharmony_ci        placeholder: "Search..."
495e41f4b71Sopenharmony_ci      })
496e41f4b71Sopenharmony_ci        .width("80%")
497e41f4b71Sopenharmony_ci        .height("40vp")
498e41f4b71Sopenharmony_ci        .border({ radius:"20vp" })
499e41f4b71Sopenharmony_ci        .onKeyPreIme((event:KeyEvent) => {
500e41f4b71Sopenharmony_ci          if (event.keyCode == KeyCode.KEYCODE_DPAD_LEFT) {
501e41f4b71Sopenharmony_ci            return true;
502e41f4b71Sopenharmony_ci          }
503e41f4b71Sopenharmony_ci          return false;
504e41f4b71Sopenharmony_ci        })
505e41f4b71Sopenharmony_ci    }
506e41f4b71Sopenharmony_ci  }
507e41f4b71Sopenharmony_ci}
508e41f4b71Sopenharmony_ci```
509