1# Multi-level Gesture Events
2
3Multi-level gesture events occur when both parent and child components receive a gesture or event bound to them. Handling such events can be tricky: The gesture and event detection is affected by a plurality of factors, with much transmission and competition involved, and an unexpected response easily occurs.
4
5This topic describes the default response sequence of multi-level gesture events and how to set related attributes to affect the response sequence of multi-level gesture events.
6
7## Default Multi-level Gesture Events
8
9### Touch Event
10
11The [touch event](../reference/apis-arkui/arkui-ts/ts-universal-events-touch.md) (**onTouch**) is the foundation of all gestures, comprising four types: Down, Move, Up, and Cancel. Gestures are built from the touch events. For example, a tap consists of a Down event followed by an Up event, while a swipe involves a Down event, a sequence of Move events, and finally an Up event. Touch events have unique characteristics:
12
131. Components that have registered for **onTouch** events receive callbacks for these events when touched, influenced by touch targets and touch control settings.
14
152. The **onTouch** event callbacks follow a closed-loop pattern. If a component receives a Down event with a specific finger ID (such as **0**), it will also receive subsequent Move and Up events for that same finger ID.
16
173. The **onTouch** event callbacks maintain consistency. If a component receives a Down event for finger ID 0 but not for finger ID 1, it will only receive touch events for finger ID 0 and will not receive any subsequent touch events for finger ID 1.
18
19For common container components (such as **Column**), **onTouch** events can be received by parent and child components at the same time, and how they are received by sibling components is subject to the layout.
20
21```ts
22ComponentA() {
23    ComponentB().onTouch(() => {})
24    ComponentC().onTouch(() => {})
25}.onTouch(() => {})
26```
27If components B and C are children of component A, then touching component B or component C also touches component A. The **onTouch** callback can be invoked by multiple components at the same time.
28Therefore, when component B is touched, the **onTouch** callback is invoked by both component A and component B, but not by component C; when component C is touched, the **onTouch** callback is invoked by both component A and component C, but not by component B.
29
30For special container components, such as **Stack**, **onTouch** events can be received by parent and child components at the same time, but how they are received by child components depends on the stacking relationship.
31
32
33```ts
34Stack A() {
35    ComponentB().onTouch(() => {})
36    ComponentC().onTouch(() => {})
37}.onTouch(() => {})
38```
39Assume that components B and C are children of Stack A, and component C is stacked on component B. Then touching component B or component C also touches Stack A. The **onTouch** callback can be invoked by multiple components at the same time. Therefore, when the overlapping area of components B and C is touched, the **onTouch** callback is invoked by both Stack A and component C, but not by component B (which is stacked by component C).
40
41### Gestures and Events
42
43All gestures and events except the touch event (**onTouch**) are implemented using basic or combined gestures. For example, the drag event is a sequence of a long press gesture and a swipe gesture.
44
45If no explicit declaration is made, only one gesture in a gesture group can be recognized for a single finger at the same time, which means that only one set callback can be invoked.
46
47Therefore, unless it is explicitly declared that multiple gestures can be recognized at the same time, only one gesture is handled at once.
48
49The response to gestures complies with the following rules:
50
511. When the parent and child components are bound to the same type of gesture, the child component responds prior to the parent component.
52
532. When a component is bound to multiple gestures, the gesture that first meets triggering conditions is preferentially triggered.
54
55```ts
56ComponentA() {
57    ComponentB().gesture(TapGesture({count: 1}))
58}.gesture(TapGesture({count: 1}))
59```
60When both the parent and child components are bound to a tap gesture, the child component responds prior to the parent component.
61Therefore, when the user touches component B, the callback of **TapGesture** bound to component B is invoked, but the callback bound to component A is not.
62
63```ts
64ComponentA()
65.gesture(
66    GestureGroup(
67        GestureMode.Exclusive,
68        TapGesture({count: 1}),
69        PanGesture({distance: 5})
70    )
71)
72```
73If the tap gesture and the swipe gesture are bound to a component in exclusive recognition mode, the gesture that first meets triggering conditions is preferentially triggered.
74If the user performs a tap operation, the callback corresponding to the tap is invoked. If the user performs a swipe operation and the swipe distance reaches the threshold, the callback corresponding to the swipe is invoked.
75
76## Handling Multi-level Gesture Events with Custom Logic
77
78You can set attributes to control the multi-level gesture event competition process.
79
80Specifically, use the **responseRegion** and **hitTestBehavior** attributes to control dispatching of touch events, thereby affecting the response to the **onTouch** events and gestures. You can also call gesture binding methods to control gesture competition and affect gesture response, but this approach does not affect triggering of **onTouch** events.
81
82### Using responseRegion
83
84The **responseRegion** attribute sets the touch target of a component, which can be larger or smaller than the layout scope of the component.
85
86```ts
87ComponentA() {
88    ComponentB()
89    .onTouch(() => {})
90    .gesture(TapGesture({count: 1}))
91    .responseRegion({Rect1, Rect2, Rect3})
92}
93.onTouch(() => {})
94.gesture(TapGesture({count: 1}))
95.responseRegion({Rect4})
96```
97In the preceding example, **.responseRegion({Rect4})** is set for component A, and as such, all touch events and gestures that fall within the Rect4 region can be received by the callback corresponding to component A.
98
99Similarly, with **.responseRegion({Rect1, Rect2, Rect3})** set for component B, all touch events and gestures that fall within the Rect1, Rect2, and Rect3 regions can be received by the callback corresponding to component B.
100
101When **responseRegion** is set for a component, the component responds to all gestures and events that occur within the designated regions, instead of those in the layout area. This may lead to no response to gestures and events in the layout-related area.
102
103The **responseRegion** attribute accepts an array consisting of multiple **Rect** values.
104
105### Using hitTestBehavior
106
107The **hitTestBehavior** attribute sets which components can respond to specific gestures and events. It is especially useful under complex multi-level event scenarios.
108
109```ts
110ComponentA() {
111    ComponentB()
112    .onTouch(() => {})
113    .gesture(TapGesture({count: 1}))
114
115    ComponentC() {
116        ComponentD()
117        .onTouch(() => {})
118        .gesture(TapGesture({count: 1}))
119    }
120    .onTouch(() => {})
121    .gesture(TapGesture({count: 1}))
122    .hitTestBehavior(HitTestMode.Block)
123}
124.onTouch(() => {})
125.gesture(TapGesture({count: 1}))
126```
127With **HitTestMode.Block**, the node responds to the hit test of a touch event, but its child node and sibling node are blocked from the hit test; as a result, neither the child node nor sibling node can receive the **onTouch** events and gestures.
128
129When **hitTestBehavior** is not set for component C, a touch in the target touch of component D triggers the **onTouch** events of components A, C, and D, as well as the tap gesture of component D.
130
131When **hitTestBehavior** is set to **HitTestMode.Block** for component C, a touch in the target touch of component D triggers the **onTouch** events of components A and C, but not the **onTouch** event of component D. In addition, because component D is blocked and its tap gesture of the component D cannot be triggered, the tap gesture of component C is triggered.
132
133```ts
134Stack A() {
135    ComponentB()
136    .onTouch(() => {})
137    .gesture(TapGesture({count: 1}))
138
139    ComponentC()
140    .onTouch(() => {})
141    .gesture(TapGesture({count: 1}))
142    .hitTestBehavior(HitTestMode.Transparent)
143}
144.onTouch(() => {})
145.gesture(TapGesture({count: 1}))
146```
147With **HitTestMode.Transparent**, both the node and its child node respond to the hit test of a touch event, and its sibling node is also considered during the hit test.
148
149If **hitTestBehavior** is not set for component C, when the overlapping area of component B and component C is touched, the **onTouch** events of Stack A and component C are triggered, the touch event of component C is triggered, and neither the **onTouch** event nor tap gesture of component B is triggered.
150
151If **hitTestBehavior** is set to **HitTestMode.Transparent** for component C, when the overlapping area of components B and C is touched, the **onTouch** events of Stack A and component C are still triggered, and the touch event of component C is also triggered; yet, because component B can receive the touch event in this case, its **onTouch** event and tap gesture are triggered.
152
153```ts
154ComponentA() {
155    ComponentB()
156    .onTouch(() => {})
157    .gesture(TapGesture({count: 1}))
158}
159.onTouch(() => {})
160.gesture(TapGesture({count: 1}))
161.hitTestBehavior(HitTestMode.None)
162```
163With **HitTestMode.None**, the node neither receives touch events nor interferes with the touch testing of its sibling components or child components.
164
165If **hitTestBehavior** is not set for component A, a touch in the target touch of component B triggers the **onTouch** events of components A and B, as well as the tap gesture of component B.
166
167When **hitTestBehavior** is set to **HitTestMode.None** for component A, a touch in the target touch of component B triggers the **onTouch** event and tap gesture of component B, but not the **onTouch** event of component A.
168
169Under simple scenarios, you are advised to set **hitTestBehavior** for each single component.
170Under complex scenarios, you are advised to set different **hitTestBehavior** values to multiple components to control the dispatching of touch events.
171
172### Calling Gesture Binding Methods
173When binding a parent component and a child component to a same gesture, you can assign different response priorities to them by using different gesture binding methods.
174
175When **.gesture** is used for gesture binding, the child component responds prior to the parent component.
176
177```ts
178ComponentA() {
179    ComponentB()
180    .gesture(TapGesture({count: 1}))
181}
182.gesture(TapGesture({count: 1}))
183```
184In the preceding example, both the parent and child components are bound to the tap gesture, and the child component responds prior to the parent component.
185In this case, when component B is touched, the tap gesture of component B is triggered, but that of component A is not.
186
187To enable the parent component to respond prior to the child component, use the **.priorityGesture** method.
188
189```ts
190ComponentA() {
191    ComponentB()
192    .gesture(TapGesture({count: 1}))
193}
194.priorityGesture(TapGesture({count: 1}))
195```
196In the preceding example, the **.priorityGesture** method is used to bind the parent component to the tap gesture, and the parent component responds prior to the child component.
197In this case, when component B is touched, the tap gesture of component A is triggered, but that of component B is not.
198
199To enable both the parent and child components to respond to a same gesture, use the **.parallelGesture** method in the parent component.
200
201```ts
202ComponentA() {
203    ComponentB()
204    .gesture(TapGesture({count: 1}))
205}
206.parallelGesture(TapGesture({count: 1}))
207```
208In the preceding example, the **.parallelGesture** method is used to bind the parent component to the tap gesture, and both the parent and child components can respond to the bound gesture.
209In this case, when component B is touched, both the tap gestures of components A and B are triggered.
210