From b6cc4567dda434ee4e4c11a667bb62b392f608d6 Mon Sep 17 00:00:00 2001 From: imaNNeoFighT Date: Fri, 19 Mar 2021 13:56:53 +0330 Subject: [PATCH] Handled click in line_chart. --- .../samples/line_chart_sample3.dart | 7 +++--- lib/src/chart/line_chart/line_chart.dart | 11 ++++---- lib/src/chart/line_chart/line_chart_data.dart | 20 +++++++++++++-- .../chart/line_chart/line_chart_painter.dart | 4 +-- .../chart/line_chart/line_chart_renderer.dart | 25 ++++++++++++++++++- 5 files changed, 54 insertions(+), 13 deletions(-) diff --git a/example/lib/line_chart/samples/line_chart_sample3.dart b/example/lib/line_chart/samples/line_chart_sample3.dart index fc52c9246..585f50464 100644 --- a/example/lib/line_chart/samples/line_chart_sample3.dart +++ b/example/lib/line_chart/samples/line_chart_sample3.dart @@ -97,9 +97,10 @@ class _LineChartSample3State extends State { }).toList(); }), touchCallback: (LineTouchResponse lineTouch) { - if (lineTouch.lineBarSpots.length == 1 && - lineTouch.touchInput is! PointerExitEvent && - lineTouch.touchInput is! PointerUpEvent) { + final desiredTouch = lineTouch.touchInput is! PointerExitEvent && + lineTouch.touchInput is! PointerUpEvent; + + if (desiredTouch && lineTouch.lineBarSpots != null) { final value = lineTouch.lineBarSpots[0].x; if (value == 0 || value == 6) { diff --git a/lib/src/chart/line_chart/line_chart.dart b/lib/src/chart/line_chart/line_chart.dart index 653c105b9..337ce316b 100644 --- a/lib/src/chart/line_chart/line_chart.dart +++ b/lib/src/chart/line_chart/line_chart.dart @@ -72,16 +72,17 @@ class _LineChartState extends AnimatedWidgetBaseState { void _handleBuiltInTouch(LineTouchResponse touchResponse) { widget.data.lineTouchData.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.lineBarSpots != null) { setState(() { - final sortedLineSpots = List.of(touchResponse.lineBarSpots); + final sortedLineSpots = List.of(touchResponse.lineBarSpots!); sortedLineSpots.sort((spot1, spot2) => spot2.y.compareTo(spot1.y)); _showingTouchedIndicators.clear(); - for (var i = 0; i < touchResponse.lineBarSpots.length; i++) { - final touchedBarSpot = touchResponse.lineBarSpots[i]; + for (var i = 0; i < touchResponse.lineBarSpots!.length; i++) { + final touchedBarSpot = touchResponse.lineBarSpots![i]; final barPos = touchedBarSpot.barIndex; _showingTouchedIndicators[barPos] = [touchedBarSpot.spotIndex]; } diff --git a/lib/src/chart/line_chart/line_chart_data.dart b/lib/src/chart/line_chart/line_chart_data.dart index 5647001f6..6f1fea2ab 100644 --- a/lib/src/chart/line_chart/line_chart_data.dart +++ b/lib/src/chart/line_chart/line_chart_data.dart @@ -1618,15 +1618,31 @@ typedef LineTouchCallback = void Function(LineTouchResponse); class LineTouchResponse extends BaseTouchResponse { /// touch happened on these spots /// (if a single line provided on the chart, [lineBarSpots]'s length will be 1 always) - final List lineBarSpots; + final List? lineBarSpots; /// If touch happens, [LineChart] processes it internally and /// passes out a list of [lineBarSpots] it gives you information about the touched spot. /// [touchInput] is the type of happened touch. + /// [clickHappened] will be true, if we detect a click event. LineTouchResponse( this.lineBarSpots, PointerEvent touchInput, - ) : super(touchInput); + bool clickHappened, + ) : super(touchInput, clickHappened); + + /// Copies current [LineTouchResponse] to a new [LineTouchResponse], + /// and replaces provided values. + LineTouchResponse copyWith({ + List? lineBarSpots, + PointerEvent? touchInput, + bool? clickHappened, + }) { + return LineTouchResponse( + lineBarSpots ?? this.lineBarSpots, + touchInput ?? this.touchInput, + clickHappened ?? this.clickHappened, + ); + } } /// It lerps a [LineChartData] to another [LineChartData] (handles animation for updating values) diff --git a/lib/src/chart/line_chart/line_chart_painter.dart b/lib/src/chart/line_chart/line_chart_painter.dart index 79a6a85c3..78d9cedf5 100644 --- a/lib/src/chart/line_chart/line_chart_painter.dart +++ b/lib/src/chart/line_chart/line_chart_painter.dart @@ -1370,7 +1370,7 @@ class LineChartPainter extends AxisChartPainter { /// Processes [PointerEvent.localPosition] and checks /// the elements of the chart that are near the offset, /// then makes a [LineTouchResponse] from the elements that has been touched. - LineTouchResponse handleTouch( + List? handleTouch( PointerEvent touchInput, Size size, PaintHolder holder, @@ -1393,7 +1393,7 @@ class LineChartPainter extends AxisChartPainter { } } - return LineTouchResponse(touchedSpots, touchInput); + return touchedSpots.isEmpty ? null : touchedSpots; } /// find the nearest spot base on the touched offset diff --git a/lib/src/chart/line_chart/line_chart_renderer.dart b/lib/src/chart/line_chart/line_chart_renderer.dart index 50a51fac8..03bdfdc7f 100644 --- a/lib/src/chart/line_chart/line_chart_renderer.dart +++ b/lib/src/chart/line_chart/line_chart_renderer.dart @@ -73,6 +73,8 @@ class RenderLineChart extends RenderBox { return PaintHolder(data, targetData, textScale); } + List? _lastTouchedSpots; + @override void performLayout() { size = computeDryLayout(constraints); @@ -97,6 +99,27 @@ class RenderLineChart extends RenderBox { @override void handleEvent(PointerEvent event, covariant BoxHitTestEntry entry) { - _touchCallback?.call(_painter.handleTouch(event, size, paintHolder)); + if (_touchCallback == null) { + return; + } + var response = LineTouchResponse(null, event, false); + + var touchedSpots = _painter.handleTouch(event, size, paintHolder); + if (touchedSpots == null || touchedSpots.isEmpty) { + _touchCallback!.call(response); + return; + } + response = response.copyWith(lineBarSpots: touchedSpots); + + if (event is PointerDownEvent) { + _lastTouchedSpots = touchedSpots; + } else if (event is PointerUpEvent) { + if (_lastTouchedSpots == touchedSpots) { + response = response.copyWith(clickHappened: true); + } + _lastTouchedSpots = null; + } + + _touchCallback!.call(response); } }