Problem Description
When the Visibility of a component is set to Visibility.None during the triggering of a gesture event, the bound swipe gesture event can still be triggered after the component is hidden.
Background Knowledge
- PanGesture is used to add swipe gesture events to components. It determines the current gesture state through onActionStart, onActionUpdate, and onActionEnd.
- Gesture Interception Enhancement provides developers with the ability to intercept gesture events for components. This allows for dynamic control over the triggering of gesture events.
Solution
When using Visibility.None to hide a component, the component no longer occupies space. However, the interface for the onActionUpdate callback has not yet been released, and the behavior is still being triggered.
This can be enhanced by using gesture interception. By obtaining the current component's gesture recognizer through the onGestureRecognizerJudgeBegin property, you can set the recognizer's setEnabled method to false when the Visibility is set to None. This indicates that the current gesture recognizer will not call back application events, thereby preventing the component from triggering drag events. An implementation example is as follows:
@Entry
@Component
struct PanGestureExample {
@State offsetX: number = 0;
@State offsetY: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
private panOption: PanGestureOptions = new PanGestureOptions({ direction: PanDirection.Left | PanDirection.Right });
private currentRecognizer: GestureRecognizer = new GestureRecognizer();
@State flag: boolean = true;
aboutToAppear(): void {
// The component will be hidden after 4 seconds.
setTimeout(() => {
this.flag = false;
// Set the enabled state of the current gesture recognizer
this.currentRecognizer.setEnabled(false);
}, 4000);
}
build() {
Column() {
Text(`offsetX: ${this.offsetX}`)
.margin(16);
Column() {
// ...
}
.margin({ left: 16 })
.height(200)
.width(300)
.border({ width: 3 })
.id('column')
.visibility(this.flag? Visibility.Visible : Visibility.None)
// Move with the top-left corner of the component as the coordinate origin
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
others: Array<GestureRecognizer>) => {
if (current) {
let target = current.getEventTargetInfo();
if (target) {
// Find the component recognizer that needs to be controlled by component ID and gesture type
if (target.getId() === 'column' &&
current.getType() === GestureControl.GestureType.PAN_GESTURE) {
// Save the identifier of the current component.
this.currentRecognizer = current;
}
}
}
console.info('event-', event, others);
return GestureJudgeResult.CONTINUE;
})
// Drag left or right to trigger the gesture event.
.gesture(
PanGesture(this.panOption)
.onActionStart((event: GestureEvent) => {
if (event) {
}
})
.onActionUpdate((event: GestureEvent) => {
if (event) {
// Implement the drag-and-drop effect.
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
}
})
.onActionEnd((event: GestureEvent) => {
if (event) {
this.positionX = this.offsetX;
this.positionY = this.offsetY;
}
})
);
}
.alignItems(HorizontalAlign.Start);
}
}
After the component disappears, finger swiping will no longer trigger the component's gesture events.
Verification Result
The implementation effect is as follows:
FAQs
Q: How to intercept web gestures?
A: You can replace the inner Scroller container with the Web container by referring to Example in the gesture interception enhancement document. In this way, web gestures can be intercepted.

Top comments (0)