diff --git a/example/lib/scatter_chart/samples/scatter_chart_sample2.dart b/example/lib/scatter_chart/samples/scatter_chart_sample2.dart index 45ccf41d4..999c2c91f 100644 --- a/example/lib/scatter_chart/samples/scatter_chart_sample2.dart +++ b/example/lib/scatter_chart/samples/scatter_chart_sample2.dart @@ -13,8 +13,6 @@ class _ScatterChartSample2State extends State { List selectedSpots = []; - int lastPanStartOnIndex = -1; - @override Widget build(BuildContext context) { return AspectRatio( @@ -99,16 +97,14 @@ class _ScatterChartSample2State extends State { tooltipBgColor: Colors.black, ), touchCallback: (ScatterTouchResponse touchResponse) { - if (touchResponse.touchInput is PointerDownEvent) { - lastPanStartOnIndex = touchResponse.touchedSpotIndex; - } else if (touchResponse.touchInput is PointerUpEvent) { - final PointerUpEvent PointerUpEven = touchResponse.touchInput; + if (touchResponse.clickHappened && touchResponse.touchedSpot != null) { + final sectionIndex = touchResponse.touchedSpot.spotIndex; // Tap happened setState(() { - if (selectedSpots.contains(lastPanStartOnIndex)) { - selectedSpots.remove(lastPanStartOnIndex); + if (selectedSpots.contains(sectionIndex)) { + selectedSpots.remove(sectionIndex); } else { - selectedSpots.add(lastPanStartOnIndex); + selectedSpots.add(sectionIndex); } }); } diff --git a/lib/src/chart/scatter_chart/scatter_chart.dart b/lib/src/chart/scatter_chart/scatter_chart.dart index f9dd0cfe0..2dd93e701 100644 --- a/lib/src/chart/scatter_chart/scatter_chart.dart +++ b/lib/src/chart/scatter_chart/scatter_chart.dart @@ -64,11 +64,12 @@ class _ScatterChartState extends AnimatedWidgetBaseState { void _handleBuiltInTouch(ScatterTouchResponse touchResponse) { widget.data.scatterTouchData.touchCallback?.call(touchResponse); - if (touchResponse.touchInput is PointerDownEvent || + final desiredTouch = touchResponse.touchInput is PointerDownEvent || touchResponse.touchInput is PointerMoveEvent || - touchResponse.touchInput is PointerHoverEvent) { + touchResponse.touchInput is PointerHoverEvent; + if (desiredTouch && touchResponse.touchedSpot != null) { setState(() { - touchedSpots = [touchResponse.touchedSpotIndex]; + touchedSpots = [touchResponse.touchedSpot!.spotIndex]; }); } else { setState(() { diff --git a/lib/src/chart/scatter_chart/scatter_chart_data.dart b/lib/src/chart/scatter_chart/scatter_chart_data.dart index 65ec4ddd9..19e79edad 100644 --- a/lib/src/chart/scatter_chart/scatter_chart_data.dart +++ b/lib/src/chart/scatter_chart/scatter_chart_data.dart @@ -290,23 +290,58 @@ typedef ScatterTouchCallback = void Function(ScatterTouchResponse); /// You can override [ScatterTouchData.touchCallback] to handle touch events, /// it gives you a [ScatterTouchResponse] and you can do whatever you want. class ScatterTouchResponse extends BaseTouchResponse { - final ScatterSpot? touchedSpot; - final int touchedSpotIndex; + final ScatterTouchedSpot? touchedSpot; /// If touch happens, [ScatterChart] processes it internally and /// passes out a [ScatterTouchResponse], it gives you information about the touched spot. /// - /// [touchedSpot], and [touchedSpotIndex] tells you + /// [touchedSpot] tells you /// in which spot (of [ScatterChartData.scatterSpots]) touch happened. /// /// [touchInput] is the type of happened touch. + /// + /// [clickHappened] will be true, if we detect a click event. ScatterTouchResponse( PointerEvent touchInput, - ScatterSpot? touchedSpot, - int touchedSpotIndex, + ScatterTouchedSpot? touchedSpot, + bool clickHappened, ) : touchedSpot = touchedSpot, - touchedSpotIndex = touchedSpotIndex, - super(touchInput); + super(touchInput, clickHappened); + + /// Copies current [ScatterTouchResponse] to a new [ScatterTouchResponse], + /// and replaces provided values. + ScatterTouchResponse copyWith({ + PointerEvent? touchInput, + ScatterTouchedSpot? touchedSpot, + bool? clickHappened, + }) { + return ScatterTouchResponse( + touchInput ?? this.touchInput, + touchedSpot ?? this.touchedSpot, + clickHappened ?? this.clickHappened, + ); + } +} + +/// Holds the touched spot data +class ScatterTouchedSpot with EquatableMixin { + + /// Touch happened on this spot + final ScatterSpot spot; + + /// Touch happened on this spot index + final int spotIndex; + + /// [spot], and [spotIndex] tells you + /// in which spot (of [ScatterChartData.scatterSpots]) touch happened. + ScatterTouchedSpot(this.spot, this.spotIndex); + + /// Used for equality check, see [EquatableMixin]. + @override + List get props => [ + spot, + spotIndex, + ]; } /// Holds representation data for showing tooltip popup on top of spots. diff --git a/lib/src/chart/scatter_chart/scatter_chart_painter.dart b/lib/src/chart/scatter_chart/scatter_chart_painter.dart index 2e4b0011b..b4c479f18 100644 --- a/lib/src/chart/scatter_chart/scatter_chart_painter.dart +++ b/lib/src/chart/scatter_chart/scatter_chart_painter.dart @@ -417,12 +417,14 @@ class ScatterChartPainter extends AxisChartPainter { return sum; } - /// Makes a [ScatterTouchResponse] based on the provided [FlTouchInput] + /// Makes a [ScatterTouchedSpot] based on the provided [touchInput] /// - /// Processes [FlTouchInput.getOffset] and checks + /// Processes [touchInput.localPosition] and checks /// the elements of the chart that are near the offset, - /// then makes a [ScatterTouchResponse] from the elements that has been touched. - ScatterTouchResponse handleTouch( + /// then makes a [ScatterTouchedSpot] from the elements that has been touched. + /// + /// Returns null if finds nothing! + ScatterTouchedSpot? handleTouch( PointerEvent touchInput, Size size, PaintHolder holder, @@ -440,10 +442,9 @@ class ScatterChartPainter extends AxisChartPainter { (spot.radius / 2) + data.scatterTouchData.touchSpotThreshold && (touchInput.localPosition.dy - spotPixelY).abs() <= (spot.radius / 2) + data.scatterTouchData.touchSpotThreshold) { - return ScatterTouchResponse(touchInput, spot, i); + return ScatterTouchedSpot(spot, i); } } - - return ScatterTouchResponse(touchInput, null, -1); + return null; } } diff --git a/lib/src/chart/scatter_chart/scatter_chart_renderer.dart b/lib/src/chart/scatter_chart/scatter_chart_renderer.dart index 0af6e884f..1b9e1cf93 100644 --- a/lib/src/chart/scatter_chart/scatter_chart_renderer.dart +++ b/lib/src/chart/scatter_chart/scatter_chart_renderer.dart @@ -75,6 +75,8 @@ class RenderScatterChart extends RenderBox { return PaintHolder(data, targetData, textScale); } + ScatterTouchedSpot? _lastTouchedSpot; + @override void performLayout() { size = computeDryLayout(constraints); @@ -99,6 +101,27 @@ class RenderScatterChart extends RenderBox { @override void handleEvent(PointerEvent event, covariant BoxHitTestEntry entry) { - _touchCallback?.call(_painter.handleTouch(event, size, paintHolder)); + if (_touchCallback == null) { + return; + } + var response = ScatterTouchResponse(event, null, false); + + var touchedSpot = _painter.handleTouch(event, size, paintHolder); + if (touchedSpot == null) { + _touchCallback!.call(response); + return; + } + response = response.copyWith(touchedSpot: touchedSpot); + + if (event is PointerDownEvent) { + _lastTouchedSpot = touchedSpot; + } else if (event is PointerUpEvent) { + if (_lastTouchedSpot != null && _lastTouchedSpot == touchedSpot) { + response = response.copyWith(clickHappened: true); + } + _lastTouchedSpot = null; + } + + _touchCallback!.call(response); } }