Problem Description
Since video playback gestures are needed, the following code cannot control volume, brightness, and progress by swiping on the screen.
Stack() {
Column() {
// Component B
}
.gesture(PanGesture()) // Expected to be able to pass through to this place
Column() {
// Component C, internally contains components D, E, F,
// expected to be able to pass this gesture event to the component above
Blank()
.parallelGesture(null, GestureMask.IgnoreInternal)
this.bottom()
}
.parallelGesture(null, GestureMask.IgnoreInternal)
}
The stacked layout is as follows: component B represents the lower-level components such as volume control and brightness, and D/E/F represent the upper-level components.
Gesture operations on components D, E, and F can be passed through to component B to control volume, brightness changes, and other operations, without executing gesture operations on components C, D, E, and F. Gesture operations are only adapted on the upper-level components D, E, and F, and cannot be passed through to the lower-level target component B.
Background Knowledge
By setting the property hitTestBehavior, the competition process of multi-level gesture events can be controlled.
- HitTestMode.Transparent: Responds to touch tests itself, but does not block sibling nodes’ touch tests.
-
HitTestMode.Block: Responds to touch tests itself and blocks the touch tests of child and sibling nodes, resulting in the
onTouchevents and gestures of child and sibling nodes not being triggered. - HitTestMode.None: Does not respond to touch tests itself, and does not block the touch control of child and sibling nodes.
Troubleshooting Process
- Examine the UI hierarchy and identify which components should respond to gestures.
- Determine that upper-layer components (C, D, E, F) should not block gestures but allow them to pass to the lower-layer component B.
- Adjust the
hitTestBehaviorproperties to ensure proper gesture propagation.
Analysis Conclusion
By setting hitTestBehavior to HitTestMode.None on upper-level components, these components will not respond to gestures themselves, allowing gesture events to be passed through to lower-level components for processing. This approach solves the gesture propagation problem in multi-layered UI layouts.
Solution
For the business scenario, sort out the UI hierarchy in the code. The expectation is that the upper-layer gesture response events will not be processed but will be passed through to the lower-layer component for processing. According to the description of the hitTestBehavior types, choose HitTestMode.None mode to achieve the effect where the upper layer does not respond, and the event is delivered to the child component to respond.
Implementation code for the above scenario is below:
@Component
struct Index {
build() {
Stack() {
Column() {
ComponentB()
.onTouch(() => {
console.info('Executing a gesture:ComponentB');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Green)
.width('90%')
.height('90%')
}
// ComponentC sets .hitTestBehavior(HitTestMode.None), it does not respond to touch tests itself
ComponentC()
.onTouch(() => {
console.info('Executing a gesture:ComponentC');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Blue)
.width('80%')
.height('80%')
.hitTestBehavior(HitTestMode.None)
}
.onTouch(() => {
console.info('Executing a gesture:StackA');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Gray)
.width('100%')
.height('100%')
.hitTestBehavior(HitTestMode.None)
}
}
@Component
struct ComponentC {
build() {
Flex({ direction: FlexDirection.Column }) {
ComponentD()
.onTouch(() => {
console.info('Executing a gesture:ComponentD');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Yellow)
.height('30%')
.width('100%')
// ComponentE sets .hitTestBehavior(HitTestMode.None), it does not respond to touch tests itself
ComponentE()
.onTouch(() => {
console.info('Executing a gesture:ComponentE');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Pink)
.height('30%')
.width('100%')
.hitTestBehavior(HitTestMode.None)
ComponentF()
.onTouch(() => {
console.info('Executing a gesture:ComponentF');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Red)
.height('30%')
.width('100%')
}.width('100%').height('100%')
.hitTestBehavior(HitTestMode.None)
}
}
Verification Result
Gesture transfer result verification:
// Touching D area:
Executing a gesture: ComponentD
Executing a gesture: ComponentB
// Touching E area:
Executing a gesture: ComponentB
// Touching F area:
Executing a gesture: ComponentF
Executing a gesture: ComponentB
// Touching C area:
Executing a gesture: ComponentB
// Touching B area:
Executing a gesture: ComponentB
// Touching A area:
// No related log output
For multi-level UI layout gesture operations, it is necessary to clarify the corresponding gesture response actions during the design process. The hitTestBehavior property can determine which components can respond to gestures and events in complex multi-level scenarios, enabling gesture propagation in business use cases

Top comments (0)