• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Custom Gesture Judgment
2
3You can use the custom gesture judgment APIs to specify whether to respond to specific gestures when they are being recognized.
4
5>  **NOTE**
6>
7>  This feature is supported since API version 11. Updates will be marked with a superscript to indicate their earliest API version.
8
9
10## onGestureJudgeBegin
11onGestureJudgeBegin(callback: (gestureInfo: GestureInfo, event: BaseGestureEvent) => GestureJudgeResult): T
12
13**Atomic service API**: This API can be used in atomic services since API version 12.
14
15**Parameters**
16| Name       | Type                   | Mandatory | Description                         |
17| ---------- | -------------------------- | ------- | ----------------------------- |
18| callback      | (gestureInfo: [GestureInfo](#gestureinfo), event: [BaseGestureEvent](#basegestureevent)) => [GestureJudgeResult](#gesturejudgeresult11) | Yes    |  Callback for custom gesture judgment. When the gesture bound to the component is accepted, the defined callback is triggered to obtain the result.|
19
20**Return value**
21
22| Type| Description|
23| -------- | -------- |
24| T | Current component.|
25
26
27## GestureJudgeResult<sup>11+</sup>
28
29**Atomic service API**: This API can be used in atomic services since API version 12.
30
31**System capability**: SystemCapability.ArkUI.ArkUI.Full
32
33| Name | Description                                  |
34| ----- | -------------------------------------- |
35| CONTINUE  | The system gesture recognition process continues.|
36| REJECT  | Recognition of the custom gesture is determined as failed.|
37
38## GestureInfo
39
40**Atomic service API**: This API can be used in atomic services since API version 12.
41
42| Name           | Type                       | Description        |
43| ---------------  | -------------------------   | -----------|
44| tag              | string                      | Gesture tag.<br>**NOTE**<br>If the event tag is not set, **undefined** or no gesture tag is returned. |
45| type             | [GestureControl.GestureType](#gesturetype12)  | Gesture type.<br>**NOTE**<br> When the gesture is a built-in gesture event of an unexposed type, the value of **type** is **-1**.|
46| isSystemGesture  | boolean                     | Whether the current gesture is a system gesture, that is, a built-in gesture of the component. **true**: The gesture is a system gesture.<br>**false**: The gesture is not a system gesture.<br>Default value: **false**|
47
48## GestureType<sup>12+</sup>
49
50**Atomic service API**: This API can be used in atomic services since API version 11.
51
52**System capability**: SystemCapability.ArkUI.ArkUI.Full
53
54| Name | Value| Description                                  |
55| ----- | -------- | -------------------------------------- |
56| TAP_GESTURE   | 0 | Tap gesture.|
57| LONG_PRESS_GESTURE  | 1 | Long press gesture.|
58| PAN_GESTURE    | 2 | Pan gesture.|
59| PINCH_GESTURE   | 3 | Pinch gesture.|
60| SWIPE_GESTURE    | 4 | Swipe gesture.|
61| ROTATION_GESTURE   | 5 | Rotation gesture.|
62| DRAG    | 6 | Drag.|
63| CLICK   | 7 | Click.|
64
65## BaseEvent<sup>8+</sup>
66
67
68| Name   | Type                                     | Description        |
69| ---------| ----------------------------------------  | -----------|
70| target   | [EventTarget](ts-universal-events-click.md#eventtarget8) | Display area of the element that triggers the gesture event.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
71| timestamp| number | Timestamp of the event. It is the interval between the time when the event is triggered and the time when the system starts.<br>Unit: ns<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
72| source   | [SourceType](ts-gesture-settings.md#sourcetype8)| Event input device.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
73| pressure<sup>9+</sup> | number | Press pressure.<br>Default value: **0**<br>Value range: [0, 1], typical value 0.913168, where higher values indicate greater pressure.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
74| tiltX<sup>9+</sup> | number | Angle between the projection of the stylus on the device plane and the x-axis.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
75| tiltY<sup>9+</sup> | number | Angle between the projection of the stylus on the device plane and the y-axis.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11.|
76| rollAngle<sup>18+</sup> | number | Angle between the stylus and the device's surface.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 18.<br>**Atomic service API**: This API can be used in atomic services since API version 18.|
77| sourceTool<sup>9+</sup> | [SourceTool](ts-gesture-settings.md#sourcetool9) | Event input source.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 9.<br>**Atomic service API**: This API can be used in atomic services since API version 11. |
78| axisHorizontal<sup>12+</sup> | number | Horizontal axis value.<br>**NOTE**<br>The value can only be obtained in the pan gesture initiated by mouse wheel scrolling or two-finger swipes on a touchpad.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 12.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
79| axisVertical<sup>12+</sup> | number | Vertical axis value.<br>**NOTE**<br>The value can only be obtained in the pan gesture initiated by mouse wheel scrolling or two-finger swipes on a touchpad.<br>**Widget capability**: This API can be used in ArkTS widgets since API version 12.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
80| getModifierKeyState<sup>12+</sup> | (Array&lt;string&gt;) => bool | Obtains the pressed status of modifier keys. For details about the error message, see the following error codes. The following modifier keys are supported: 'Ctrl'\|'Alt'\|'Shift'\|'Fn'. This API does not work for the Fn key on an externally connected keyboard.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
81| deviceId<sup>12+</sup> | number | ID of the input device that triggers the event.<br>**Atomic service API**: This API can be used in atomic services since API version 12.|
82| targetDisplayId<sup>15+</sup> | number | ID of the screen where the event occurs.<br>Default value: **0**<br>Value range: [0, +∞).<br>**Atomic service API**: This API can be used in atomic services since API version 15.|
83
84**Error codes**
85
86For details about the error codes, see [Universal Error Codes](../../errorcode-universal.md).
87
88| ID| Error Message|
89| ------- | -------- |
90| 401 | Parameter error. Possible causes: 1. Incorrect parameter types. 2. Parameter verification failed. |
91
92## BaseGestureEvent
93Inherits from [BaseEvent](#baseevent8).
94
95**Atomic service API**: This API can be used in atomic services since API version 12.
96
97| Name     | Type                                     | Description        |
98| ---------  | ----------------------------------------  | -----------|
99| fingerList | [FingerInfo[]](ts-gesture-settings.md#fingerinfo8) | Information about all fingers that trigger the event. |
100
101## TapGestureEvent
102Extended from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
103
104**Atomic service API**: This API can be used in atomic services since API version 12.
105
106## LongPressGestureEvent
107Inherits from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
108
109**Atomic service API**: This API can be used in atomic services since API version 12.
110
111| Name     | Type                                     | Description        |
112| ---------  | ----------------------------------------  | -----------|
113| repeat     | boolean | Whether the event is repeated. <br>**true**: The event is repeated.<br>**false**: The event is not repeated. |
114
115## PanGestureEvent
116Inherits from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
117
118**Atomic service API**: This API can be used in atomic services since API version 12.
119
120| Name     | Type                                     | Description        |
121| ---------  | ----------------------------------------  | -----------|
122| offsetX    | number | Offset of the gesture event on the x-axis relative to the original area of the current component, in vp. A positive value means to pan from left to right, and a negative value means the opposite. |
123| offsetY    | number | Offset of the gesture event on the y-axis relative to the original area of the current component, in vp. A positive value means to pan from top to bottom, and a negative value means the opposite. |
124| velocityX  | number | Velocity along the x-axis. The origin of the coordinate axis is the upper left corner of the screen. The velocity is positive if the movement is from left to right, and it is negative if the movement is from right to left. The unit is vp/s. |
125| velocityY  | number | Velocity along the y-axis. The origin of the coordinate axis is the upper left corner of the screen. The velocity is positive if the movement is from top to bottom, and it is negative if the movement is from bottom to top. The unit is vp/s.|
126| velocity   | number | Velocity along the main axis. The value is the arithmetic square root of the sum of squares of the velocity along the x- and y-axis. The unit is vp/s. |
127
128## PinchGestureEvent
129
130**Atomic service API**: This API can be used in atomic services since API version 12.
131
132Inherits from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
133| Name        | Type                                     | Description        |
134| ------------  | ----------------------------------------  | -----------|
135| scale         | number | Scale factor. |
136| pinchCenterX  | number | X coordinate of the center of the pinch gesture, in vp, relative to the original area of the current component. |
137| pinchCenterY  | number | Y coordinate of the center of the pinch gesture, in vp, relative to the original area of the current component. |
138
139## RotationGestureEvent
140
141**Atomic service API**: This API can be used in atomic services since API version 12.
142
143Inherits from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
144| Name        | Type                                     | Description        |
145| ------------  | ----------------------------------------  | -----------|
146| angle         | number | Rotation angle, in deg.<br>**NOTE**<br>Angle calculation method: After a swipe gesture is recognized, a line connecting the two fingers is identified as the initial line. As the fingers swipe, the line between the fingers rotates. Based on the coordinates of the initial line's and current line's end points, the arc tangent function is used to calculate the respective included angle of the points relative to the horizontal direction by using the following formula: Rotation angle = arctan2(cy2-cy1,cx2-cx1) - arctan2(y2-y1,x2-x1). The initial line is used as the coordinate system. Values from 0 to 180 degrees represent clockwise rotation, while values from –180 to 0 degrees represent counterclockwise rotation. |
147
148## SwipeGestureEvent
149Inherits from [BaseGestureEvent](#basegestureevent). This object can be passed in as the **event** parameter of [onGestureJudgeBegin](#ongesturejudgebegin).
150
151**Atomic service API**: This API can be used in atomic services since API version 12.
152
153| Name        | Type                                     | Description        |
154| ------------  | ----------------------------------------  | -----------|
155| angle         | number | Angle of the swipe gesture, that is, the change in the included angle between the line segment created by the two fingers and the horizontal direction. The unit is deg.<br>**NOTE**<br>Angle calculation method: After a swipe gesture is recognized, a line connecting the two fingers is identified as the initial line. As the fingers swipe, the line between the fingers rotates. Based on the coordinates of the initial line's and current line's end points, the arc tangent function is used to calculate the respective included angle of the points relative to the horizontal direction by using the following formula: Rotation angle = arctan2(cy2-cy1,cx2-cx1) - arctan2(y2-y1,x2-x1). The initial line is used as the coordinate system. The clockwise rotation is 0 to 180 degrees, and the counter-clockwise rotation is –180 to 0 degrees.|
156| speed         | number | Swipe gesture speed, that is, the average swipe speed of all fingers relative to the original area of the current component. The unit is vp/s. |
157## Example
158
159### Example 1: Implementing Custom Gesture Judgment
160
161This example demonstrates how to implement custom judgment for long press, swipe, and pan gestures using **onGestureJudgeBegin**.
162
163```ts
164// xxx.ets
165@Entry
166@Component
167struct Index {
168  @State message: string = '';
169
170  build() {
171    Column() {
172      Row({ space: 20 }) {
173        Text(this.message).width(200).height(80).backgroundColor(Color.Pink)
174          .fontSize(25)
175      }.margin(20)
176    }
177    .width('100%')
178    .height(200)
179    .borderWidth(2)
180    .onDragStart(() => {
181      this.message = 'drag'
182      console.log("Drag start.")
183    })
184    .gesture(
185      TapGesture()
186        .tag("tap1")// Tag for the tap gesture.
187        .onAction(() => {
188          this.message = 'tap1'
189        })
190    )
191    .gesture(
192      LongPressGesture()
193        .tag("longPress1")// Tag for the long press gesture.
194        .onAction(() => {
195          this.message = 'longPress'
196        })
197    )
198    .gesture(
199      SwipeGesture()
200        .tag("swipe1")// Tag for the swipe gesture.
201        .onAction(() => {
202          this.message = 'swipe1'
203        })
204    )
205    .gesture(
206      PanGesture()
207        .tag("pan1")// Tag for the pan gesture.
208        .onActionStart(() => {
209          this.message = 'pan1'
210        })
211    )
212    .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => {
213      // If the gesture type is a long press gesture, convert the event to a long press gesture event.
214      if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) {
215        let longPressEvent = event as LongPressGestureEvent;
216        console.log("repeat " + longPressEvent.repeat)
217      }
218      // If the gesture type is a swipe gesture, convert the event to a swipe gesture event.
219      if (gestureInfo.type == GestureControl.GestureType.SWIPE_GESTURE) {
220        let swipeEvent = event as SwipeGestureEvent;
221        console.log("angle " + swipeEvent.angle)
222      }
223      // If the gesture type is a pan gesture, convert the event to a pan gesture event.
224      if (gestureInfo.type == GestureControl.GestureType.PAN_GESTURE) {
225        let panEvent = event as PanGestureEvent;
226        console.log("velocity " + panEvent.velocity)
227      }
228      // Custom criteria
229      if (gestureInfo.type == GestureControl.GestureType.DRAG) {
230        // If REJECT is returned, the drag gesture fails.
231        return GestureJudgeResult.REJECT;
232      } else if (gestureInfo.tag == 'longPress1' && event.fingerList.length > 0 && event.fingerList[0].localY < 100) {
233        // If CONTINUE is returned, the system recognition result is retained.
234        return GestureJudgeResult.CONTINUE;
235      }
236      return GestureJudgeResult.CONTINUE;
237    })
238  }
239}
240```
241![gestures1](figures/gestures1.gif)
242
243### Example 2: Implementing Custom Area Gesture Judgment
244
245This example demonstrates how to use **onGestureJudgeBegin** to determine whether to respond to long press and pan gestures based on the area.
246
247```ts
248// xxx.ets
249import { promptAction } from '@kit.ArkUI';
250
251@Entry
252@Component
253struct Index {
254  scroller: Scroller = new Scroller()
255
256  build() {
257    Scroll(this.scroller) {
258      Column({ space: 8 }) {
259        Text("The upper red area is bound to the long press gesture, and the lower blue area is bound to a drag gesture. If a pan is performed after a long press in the upper red area, the area only responds to the long press. In the same case, the lower blue area only responds to the drag.").width('100%').fontSize(20).fontColor('0xffdd00')
260          .backgroundColor(0xeeddaa00)
261        Stack({ alignContent: Alignment.Center }) {
262          Column() {
263            // Simulate the upper and lower half areas.
264            Stack().width('200vp').height('100vp').backgroundColor(Color.Red)
265            Stack().width('200vp').height('100vp').backgroundColor(Color.Blue)
266          }.width('200vp').height('200vp')
267          // The lower half area of the stack is an image area bound to the pan gesture.
268          Image($r('sys.media.ohos_app_icon'))
269            .draggable(true)
270            .onDragStart(()=>{
271              promptAction.showToast({ message: "When the blue area is dragged, the image responds" })
272            })
273            .width('200vp').height('200vp')
274          // The upper half area of the stack is a floating area bound to the long press gesture.
275          Stack() {
276          }
277          .width('200vp')
278          .height('200vp')
279          .hitTestBehavior(HitTestMode.Transparent)
280          .onGestureJudgeBegin((gestureInfo: GestureInfo, event: BaseGestureEvent) => {
281            // Check whether the tag has a value.
282            if (gestureInfo.tag) {
283              console.log("gestureInfo tag" + gestureInfo.tag.toString())
284            }
285            console.log("gestureInfo Type " + gestureInfo.type.toString() + " isSystemGesture " + gestureInfo.isSystemGesture);
286            console.log("pressure " + event.pressure + " fingerList.length " + event.fingerList.length
287            + " timeStamp " + event.timestamp + " sourceType " + event.source.toString() + " titleX " + event.tiltX + " titleY " + event.tiltY + " rollAngle " + event.rollAngle + " sourcePool " + event.sourceTool.toString());
288            // If the gesture is a long press gesture, check whether the touch position is in the upper half area.
289            if (gestureInfo.type == GestureControl.GestureType.LONG_PRESS_GESTURE) {
290              if (event.fingerList.length > 0 && event.fingerList[0].localY < 100) {
291                return GestureJudgeResult.CONTINUE
292              } else {
293                return GestureJudgeResult.REJECT
294              }
295            }
296            return GestureJudgeResult.CONTINUE
297          })
298          .gesture(GestureGroup(GestureMode.Parallel,
299            LongPressGesture()
300              .onAction((event: GestureEvent) => {
301                promptAction.showToast({ message: "When long pressed, the red area responds." })
302              })
303              .tag("tap111")
304          ))
305
306        }.width('100%')
307      }.width('100%')
308    }
309  }
310}
311```
312![gestures2](figures/gestures2.gif)
313