equirement Description
Due to the need to implement video playback control gestures, the following code cannot control volume, brightness, and progress by swiping on the screen.
Stack() {
Column() {
// Component B
}
.gesture(PanGesture()) // Expected to receive the passed gesture here
Column() {
// Component C, containing subcomponents D, E, and F; expected to pass the gesture event upward to the component above
Blank()
.parallelGesture(null, GestureMask.IgnoreInternal)
this.bottom()
}
.parallelGesture(null, GestureMask.IgnoreInternal)
}
The layered layout is shown below: Component B represents lower-level elements such as volume and brightness controls, while D/E/F represent upper-layer components.
Expected result:
Gesture operations on components D, E, and F should be passed through to component B, enabling control of volume, brightness, and progress, without triggering gesture operations in C, D, E, or F.
Actual issue:
Gestures only work on the upper-layer components D, E, and F and cannot be passed down to the target lower-layer component B.
Background Knowledge
You can control the multi-layer gesture event competition process using the hitTestBehavior property.
- HitTestMode.Transparent: Responds to touch tests itself, but does not block sibling nodes’ touch tests.
-
HitTestMode.Block: Responds to touch tests itself and blocks touch tests for child and sibling nodes, preventing their
onTouchevents and gestures from being triggered. - HitTestMode.None: Does not respond to touch tests and does not block touch controls of child or sibling nodes.
Implementation Steps
To meet the business requirements, organize the UI hierarchy so that the upper-layer components do not handle gesture responses but instead pass them to the lower-layer components for processing.
According to the hitTestBehavior definition, selecting HitTestMode.None ensures that upper layers do not respond, allowing gesture events to pass through to child nodes.
Code Snippet / Configuration
@Entry
@Component
struct Index {
build() {
Stack() {
Column() {
Column() {
Text('ColumnB')
}
.onTouch(() => {
console.info('Executing a gesture:ComponentB');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Green)
.width('90%')
.height('90%')
}
// Component C uses .hitTestBehavior(HitTestMode.None), so it does not respond to touch tests
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 }) {
Column() {
Text('ColumnD')
}
.onTouch(() => {
console.info('Executing a gesture:ComponentD');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Yellow)
.height('30%')
.width('100%')
// Component E uses .hitTestBehavior(HitTestMode.None), so it does not respond to touch tests
Column() {
Text('ColumnE')
}
.onTouch(() => {
console.info('Executing a gesture:ComponentE');
})
.gesture(TapGesture({ count: 1 }))
.backgroundColor(Color.Pink)
.height('30%')
.width('100%')
.hitTestBehavior(HitTestMode.None)
Column() {
Text('ColumnF')
}
.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)
}
}
Test Results
Gesture propagation results when touching different colored areas:
Touching area D:
Executing a gesture:ComponentD
Executing a gesture:ComponentB
Touching area E:
Executing a gesture:ComponentB
Touching area F:
Executing a gesture:ComponentF
Executing a gesture:ComponentB
Touching area C:
Executing a gesture:ComponentB
Touching area B:
Executing a gesture:ComponentB
Touching area A:
// No related log output
Limitations or Considerations
This example supports API Version 19 Release and above.
This example supports HarmonyOS 5.1.1 Release SDK and above.
Compilation and execution require DevEco Studio 5.1.1 Release or later.

Top comments (0)