Gesturedetector on top of chart

I am trying to have specific information from the chart be copyable/pastable, to this end I have created a popup menu that should show up with a double tap. To make this possible I wrapped my chart in a Gesturedetector, which only recognizes a double tap. This however does not work. The only time it works is if I put the chart into an IgnorePointer, but then I can't zoom/pan use trackball etc.

I have uploaded a video showing the double tap and menu button appearing.

Thanks in advance.

Here is a code snippet: 

child: GestureDetector(
child: IgnorePointer(child: SimulationChart(id: widget.id)) ,
onDoubleTap: () => showMenu(
context: context,
position: RelativeRect.fromLTRB(context.size.width / 2, context.size.height / 2, context.size.width / 2, context.size.height),
items: [
PopupMenuItem(
height: 25,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
PopupMenuItem(
value: ActionType.copy,
child: Text("Copy")
),
PopupMenuItem(
value: ActionType.paste,
child: Text("Paste")
),
],
),
),
],
).then((action) {
if (action == ActionType.copy) {
Scaffold.of(context).hideCurrentSnackBar();
Scaffold.of(context).showSnackBar(SnackBar(
action: SnackBarAction(label: "Undo", onPressed: () {}),
content: Text("Copied to clipboard"),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))
));
} else if (action == ActionType.paste) {
Scaffold.of(context).hideCurrentSnackBar();
Scaffold.of(context).showSnackBar(SnackBar(
action: SnackBarAction(label: "Undo", onPressed: () {}),
content: Text("Pasted from clipboard"),
behavior: SnackBarBehavior.floating,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(5))
));
} else {
return;
}
}),
// Scaffold.of(context).showSnackBar(SnackBar(content: Text("Copied"))),
// onLongPressEnd: (_) => ,
behavior: simulationManager.addMode ? HitTestBehavior.deferToChild : HitTestBehavior.translucent,
)
)

Attachment: Schermopname_20200315_om_11.39.44.mov_c625d62b.zip

3 Replies

DD Dharanidharan Dharmasivam Syncfusion Team March 16, 2020 11:52 AM UTC

Hi Luca, 
 
Greetings from Syncfusion. We have analyzed your requirements with the provided code snippet and video. When IgnorePointer widget with ignoring property is set to true, the IgnorePointer and its sub-widgets will be invisible for touch interactions. So, while placing the chart widget in IgnorePointer widget the panning/zooming is not working.  
Your requirement can be achieved as a workaround using our TooltipBehavior class. Using this class, we have overridden the onDoubleTap method. You can change this based on your scenario. 
 
 
class CustomTooltipBehaviour extends TooltipBehavior { 
// Other configurations 
  @override 
  void onDoubleTap(double xPos, double yPos) { 
    print('Tapped on chart'); 
    super.onDoubleTap(xPos, yPos); 
  } 
} 
 
SfCartesianChart( 
              // The tooltip activation mode need to doubleTap 
             tooltipBehavior: CustomTooltipBehaviour( 
                  enable: true, activationMode: ActivationMode.doubleTap) 
           // Other configurations 
) 
 
 
The sample for reference can be found below. 
 
Note: To achieve this, tooltip activation mode needs to be doubleTap. 
 
Thanks, 
Dharani. 



RO Roberto March 15, 2024 08:56 PM UTC

This is how you do it:

Double and long-tap are captured but single tap still goes to chart tool tip... Works perfectly

Listener(
onPointerDown: (PointerDownEvent event) {
_isLongPress = false; // Reset long press state
// Start or restart the double tap timer
if (_doubleTapTimer == null || !_doubleTapTimer!.isActive) {
_doubleTapTimer = Timer(Duration(milliseconds: 300), () {
// If timer completes without a second tap, it's either a single tap or the start of a long press
_isDoubleTap = false;
});
} else {
// If a second tap occurs, cancel the double tap timer, recognize it as a double tap
_doubleTapTimer?.cancel();
_isDoubleTap = true;
// Handle double tap
print("Double Tap Detected");
setState(() => showYAxis = !showYAxis);
}
// Start long press timer
_longPressTimer = Timer(const Duration(milliseconds: 500), () {
// Timer completes without pointer up, recognize as long press
_isLongPress = true;
// Todo: Implement long-tap full-screen logic
// Handle long press
// You might want to use setState or other methods to update your UI or state
});
},
onPointerUp: (PointerUpEvent event) {
// Cancel long press timer on pointer up to prevent it from triggering if the user releases before it's a long press
_longPressTimer?.cancel();
if (_isDoubleTap) {
// Reset double tap state after handling
_isDoubleTap = false;
} else if (!_isLongPress) {
// If it's not a long press or double tap, you could handle it as a single tap, if needed.
// Note: Since we want single taps to go through to the chart, we might not need to do anything here.
}
// Reset long press state
_isLongPress = false;
},
child: SfCartesianChart(
...
);


PS Preethika Selvam Syncfusion Team March 18, 2024 01:58 PM UTC

Hi Roberto,


We are happy to hear that you have found a new solution. If you have any further queries, please get back to us. We are always happy to assist you.


Regards,

Preethika Selvam.


Loader.
Up arrow icon