1e41f4b71Sopenharmony_ci# Combined Gestures
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ciA combined gesture is a combination of multiple single gestures. Its recognition mode is subject to **GestureMode** passed in **GestureGroup**. Three recognition modes are supported: [sequential recognition](#sequential-recognition), [parallel recognition](#parallel-recognition), and [exclusive recognition](#exclusive-recognition).
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci```ts
7e41f4b71Sopenharmony_ciGestureGroup(mode:GestureMode, gesture:GestureType[])
8e41f4b71Sopenharmony_ci```
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci- **mode**: recognition mode of combined gestures. The value belongs to the **GestureMode** enumeration class.
12e41f4b71Sopenharmony_ci
13e41f4b71Sopenharmony_ci- **gesture**: array of multiple gestures.
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci## Sequential Recognition
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ciFor sequential recognition, the value of **GestureMode** is **Sequence**. In this gesture recognition mode, gestures are recognized in the order in which they were registered until they are all recognized successfully. If any of the registered gestures fails to be recognized, subsequent gestures will also fail. Only the last gesture recognized responds to the **onActionEnd** event.
19e41f4b71Sopenharmony_ci
20e41f4b71Sopenharmony_ciIn the following example, the combined gestures for continuous recognition are the long press gesture and pan gesture.
21e41f4b71Sopenharmony_ci
22e41f4b71Sopenharmony_ciThe **translate** attribute is bound to a **Column** component. You can set the attribute to translate the component. Then, bind **LongPressGesture** and **PanGesture** to the component in the **Sequence** gesture mode. When a long press gesture is recognized, the displayed number is updated. When the user drags the component after the long press gesture, the component is dragged based on the callback function of the pan gesture.
23e41f4b71Sopenharmony_ci
24e41f4b71Sopenharmony_ci```ts
25e41f4b71Sopenharmony_ci// xxx.ets
26e41f4b71Sopenharmony_ci@Entry
27e41f4b71Sopenharmony_ci@Component
28e41f4b71Sopenharmony_cistruct Index {
29e41f4b71Sopenharmony_ci  @State offsetX: number = 0;
30e41f4b71Sopenharmony_ci  @State offsetY: number = 0;
31e41f4b71Sopenharmony_ci  @State count: number = 0;
32e41f4b71Sopenharmony_ci  @State positionX: number = 0;
33e41f4b71Sopenharmony_ci  @State positionY: number = 0;
34e41f4b71Sopenharmony_ci  @State borderStyles: BorderStyle = BorderStyle.Solid
35e41f4b71Sopenharmony_ci
36e41f4b71Sopenharmony_ci  build() {
37e41f4b71Sopenharmony_ci    Column() {
38e41f4b71Sopenharmony_ci      Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
39e41f4b71Sopenharmony_ci        .fontSize(28)
40e41f4b71Sopenharmony_ci    }.margin(10)
41e41f4b71Sopenharmony_ci    .borderWidth(1)
42e41f4b71Sopenharmony_ci    // Bind the translate attribute to translate the component.
43e41f4b71Sopenharmony_ci    .translate({ x: this.offsetX, y: this.offsetY, z: 0 })
44e41f4b71Sopenharmony_ci    .height(250)
45e41f4b71Sopenharmony_ci    .width(300)
46e41f4b71Sopenharmony_ci    // The following combined gestures are recognized in sequence. When the long press gesture event is not triggered correctly, the pan gesture event is not triggered.
47e41f4b71Sopenharmony_ci    .gesture(
48e41f4b71Sopenharmony_ci      // Set the gesture mode to Sequence.
49e41f4b71Sopenharmony_ci      GestureGroup(GestureMode.Sequence,
50e41f4b71Sopenharmony_ci        // The first gesture recognized in the combined gestures is the long press gesture, which can be responded to for multiple times.
51e41f4b71Sopenharmony_ci        LongPressGesture({ repeat: true })
52e41f4b71Sopenharmony_ci          // When the long press gesture is successfully recognized, the value of count displayed on the <Text> component is increased.
53e41f4b71Sopenharmony_ci          .onAction((event: GestureEvent|undefined) => {
54e41f4b71Sopenharmony_ci            if(event){
55e41f4b71Sopenharmony_ci              if (event.repeat) {
56e41f4b71Sopenharmony_ci                this.count++;
57e41f4b71Sopenharmony_ci              }
58e41f4b71Sopenharmony_ci            }
59e41f4b71Sopenharmony_ci            console.info('LongPress onAction');
60e41f4b71Sopenharmony_ci          })
61e41f4b71Sopenharmony_ci          .onActionEnd(() => {
62e41f4b71Sopenharmony_ci            console.info('LongPress end');
63e41f4b71Sopenharmony_ci          }),
64e41f4b71Sopenharmony_ci        // The pan gesture is triggered when the component is dragged after the long press gesture is recognized.
65e41f4b71Sopenharmony_ci        PanGesture()
66e41f4b71Sopenharmony_ci          .onActionStart(() => {
67e41f4b71Sopenharmony_ci            this.borderStyles = BorderStyle.Dashed;
68e41f4b71Sopenharmony_ci            console.info('pan start');
69e41f4b71Sopenharmony_ci          })
70e41f4b71Sopenharmony_ci            // When the gesture is triggered, the pan distance is obtained based on the callback, and the displacement distance of the component is modified. In this way, the component is translated.
71e41f4b71Sopenharmony_ci          .onActionUpdate((event: GestureEvent|undefined) => {
72e41f4b71Sopenharmony_ci            if(event){
73e41f4b71Sopenharmony_ci              this.offsetX = (this.positionX + event.offsetX);
74e41f4b71Sopenharmony_ci              this.offsetY = this.positionY + event.offsetY;
75e41f4b71Sopenharmony_ci            }
76e41f4b71Sopenharmony_ci            console.info('pan update');
77e41f4b71Sopenharmony_ci          })
78e41f4b71Sopenharmony_ci          .onActionEnd(() => {
79e41f4b71Sopenharmony_ci            this.positionX = this.offsetX;
80e41f4b71Sopenharmony_ci            this.positionY = this.offsetY;
81e41f4b71Sopenharmony_ci            this.borderStyles = BorderStyle.Solid;
82e41f4b71Sopenharmony_ci          })
83e41f4b71Sopenharmony_ci      )
84e41f4b71Sopenharmony_ci      .onCancel(() => {
85e41f4b71Sopenharmony_ci        console.log("sequence gesture canceled")
86e41f4b71Sopenharmony_ci      })
87e41f4b71Sopenharmony_ci    )
88e41f4b71Sopenharmony_ci  }
89e41f4b71Sopenharmony_ci}
90e41f4b71Sopenharmony_ci```
91e41f4b71Sopenharmony_ci
92e41f4b71Sopenharmony_ci
93e41f4b71Sopenharmony_ci![sequence](figures/sequence.gif)
94e41f4b71Sopenharmony_ci
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ci>**NOTE**
97e41f4b71Sopenharmony_ci>
98e41f4b71Sopenharmony_ci>The drag event is a typical use case of sequential recognition on the long press gesture and pan gesture. It is triggered only when the user performs a pan gesture within the preset time frame after a long press gesture is recognized. If the long press gesture is not recognized or the pan gesture is not performed within the preset time frame, the drag event will not be triggered.
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci
101e41f4b71Sopenharmony_ci## Parallel Recognition
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ciFor parallel recognition, the value of **GestureMode** is **Parallel**. In this gesture recognition mode, gestures registered in the combined gestures will be recognized at the same time until they are all recognized successfully. The gestures are recognized in parallel without affecting each other.
104e41f4b71Sopenharmony_ci
105e41f4b71Sopenharmony_ciFor example, if the tap gesture and the double-tap gesture are bound to the **Column** component in parallel recognition mode, they can be recognized at the same time, and the recognition of these two gestures does not interfere with each other. 
106e41f4b71Sopenharmony_ci
107e41f4b71Sopenharmony_ci```ts
108e41f4b71Sopenharmony_ci// xxx.ets
109e41f4b71Sopenharmony_ci@Entry
110e41f4b71Sopenharmony_ci@Component
111e41f4b71Sopenharmony_cistruct Index {
112e41f4b71Sopenharmony_ci  @State count1: number = 0;
113e41f4b71Sopenharmony_ci  @State count2: number = 0;
114e41f4b71Sopenharmony_ci
115e41f4b71Sopenharmony_ci  build() {
116e41f4b71Sopenharmony_ci    Column() {
117e41f4b71Sopenharmony_ci      Text('Parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
118e41f4b71Sopenharmony_ci        .fontSize(28)
119e41f4b71Sopenharmony_ci    }
120e41f4b71Sopenharmony_ci    .height(200)
121e41f4b71Sopenharmony_ci    .width('100%')
122e41f4b71Sopenharmony_ci    // The following combined gestures are recognized in parallel mode. After a tap gesture is recognized successfully, if another tap gesture is recognized within the specified time frame, a double-tap gesture will also be recognized.
123e41f4b71Sopenharmony_ci    .gesture(
124e41f4b71Sopenharmony_ci      GestureGroup(GestureMode.Parallel,
125e41f4b71Sopenharmony_ci        TapGesture({ count: 1 })
126e41f4b71Sopenharmony_ci          .onAction(() => {
127e41f4b71Sopenharmony_ci            this.count1++;
128e41f4b71Sopenharmony_ci          }),
129e41f4b71Sopenharmony_ci        TapGesture({ count: 2 })
130e41f4b71Sopenharmony_ci          .onAction(() => {
131e41f4b71Sopenharmony_ci            this.count2++;
132e41f4b71Sopenharmony_ci          })
133e41f4b71Sopenharmony_ci      )
134e41f4b71Sopenharmony_ci    )
135e41f4b71Sopenharmony_ci  }
136e41f4b71Sopenharmony_ci}
137e41f4b71Sopenharmony_ci```
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci
140e41f4b71Sopenharmony_ci![parallel](figures/parallel.gif)
141e41f4b71Sopenharmony_ci
142e41f4b71Sopenharmony_ci
143e41f4b71Sopenharmony_ci>**NOTE**
144e41f4b71Sopenharmony_ci>
145e41f4b71Sopenharmony_ci>After a tap gesture and a double-tap gesture are combined for parallel recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
146e41f4b71Sopenharmony_ci>
147e41f4b71Sopenharmony_ci>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
148e41f4b71Sopenharmony_ci>
149e41f4b71Sopenharmony_ci>When there are two taps and the interval between the two taps is within a specified period (300 ms by default), two tap events and one double-tap event are triggered.
150e41f4b71Sopenharmony_ci>
151e41f4b71Sopenharmony_ci>When there are two taps, but the interval between the two taps exceeds the specified time, two tap events are triggered but the double-tap event is not triggered.
152e41f4b71Sopenharmony_ci
153e41f4b71Sopenharmony_ci
154e41f4b71Sopenharmony_ci## Exclusive Recognition
155e41f4b71Sopenharmony_ci
156e41f4b71Sopenharmony_ciFor exclusive recognition, the value of **GestureMode** is **Exclusive**. In this gesture recognition mode, all registered gestures are recognized at once. Once any of the gestures is recognized successfully, the gesture recognition ends, and all other gestures fail to be recognized.
157e41f4b71Sopenharmony_ci
158e41f4b71Sopenharmony_ciFor example, when the tap gesture and the double-tap gesture are bound to the **Column** component in exclusive recognition mode, if you bind the tap gesture first, followed by the double-tap, the double-tap gesture won't be recognized because the tap consumes all touch events. However, if you bind the double-tap gesture first, it will be recognized without triggering the tap.
159e41f4b71Sopenharmony_ci
160e41f4b71Sopenharmony_ci```ts
161e41f4b71Sopenharmony_ci// xxx.ets
162e41f4b71Sopenharmony_ci@Entry
163e41f4b71Sopenharmony_ci@Component
164e41f4b71Sopenharmony_cistruct Index {
165e41f4b71Sopenharmony_ci  @State count1: number = 0;
166e41f4b71Sopenharmony_ci  @State count2: number = 0;
167e41f4b71Sopenharmony_ci
168e41f4b71Sopenharmony_ci  build() {
169e41f4b71Sopenharmony_ci    Column() {
170e41f4b71Sopenharmony_ci      Text('Exclusive gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
171e41f4b71Sopenharmony_ci        .fontSize(28)
172e41f4b71Sopenharmony_ci    }
173e41f4b71Sopenharmony_ci    .height(200)
174e41f4b71Sopenharmony_ci    .width('100%')
175e41f4b71Sopenharmony_ci    // The following combined gestures are mutually exclusive. After the tap gesture is recognized successfully, the double-tap gesture fails to be recognized.
176e41f4b71Sopenharmony_ci    .gesture(
177e41f4b71Sopenharmony_ci      GestureGroup(GestureMode.Exclusive,
178e41f4b71Sopenharmony_ci        TapGesture({ count: 1 })
179e41f4b71Sopenharmony_ci          .onAction(() => {
180e41f4b71Sopenharmony_ci            this.count1++;
181e41f4b71Sopenharmony_ci          }),
182e41f4b71Sopenharmony_ci        TapGesture({ count: 2 })
183e41f4b71Sopenharmony_ci          .onAction(() => {
184e41f4b71Sopenharmony_ci            this.count2++;
185e41f4b71Sopenharmony_ci          })
186e41f4b71Sopenharmony_ci      )
187e41f4b71Sopenharmony_ci    )
188e41f4b71Sopenharmony_ci  }
189e41f4b71Sopenharmony_ci}
190e41f4b71Sopenharmony_ci```
191e41f4b71Sopenharmony_ci
192e41f4b71Sopenharmony_ci
193e41f4b71Sopenharmony_ci![exclusive](figures/exclusive.gif)
194e41f4b71Sopenharmony_ci
195e41f4b71Sopenharmony_ci
196e41f4b71Sopenharmony_ci>**NOTE**
197e41f4b71Sopenharmony_ci>
198e41f4b71Sopenharmony_ci>After a tap gesture and a double-tap gesture are combined for exclusive recognition, when taps are performed in an area, the tap gesture and the double-tap gesture are recognized at the same time.
199e41f4b71Sopenharmony_ci>
200e41f4b71Sopenharmony_ci>When there is only a single tap, the tap gesture is recognized, but the double-tap gesture fails to be recognized.
201e41f4b71Sopenharmony_ci>
202e41f4b71Sopenharmony_ci>When there are two taps, the gesture response depends on the order of gesture binding. If you bind the tap gesture first, followed by the double-tap gesture, the tap gesture will be recognized on the first tap, causing the double-tap gesture to fail. Even if the second tap is performed within the specified time, the double-tap gesture event is not responded to. Instead, another tap gesture event is triggered. Conversely, if you bind the double-tap gesture first, it will be recognized without triggering the tap gesture.
203