syncfusion / flutter-widgets

Syncfusion Flutter widgets libraries include high quality UI widgets and file-format packages to help you create rich, high-quality applications for iOS, Android, and web from a single code base.
1.56k stars 759 forks source link

[SfCartesianChart] On tap callback for Line chart with zoom pan behavior enabled #1506

Closed siiimaay closed 9 months ago

siiimaay commented 10 months ago

Hey,

I’m having issue where I need to use panning in x-axis within Line chart and also be able to click to chart plot area to show dialog (aim is kind of click and enlarge chart in a dialog). I saw your answers for issues related other chart types by using RawGestureDetector, I’ve tried to use but onTap is not called in below code, and overriding rejectGesture by calling acceptGesture is giving '_down == null && _up == null': is not true

I’m able to use instance.onTapDown but this is called even I do scroll horizontally using ZoomPanBehaviour, any workaround for enabling tapping in plot area?

RawGestureDetector(
                          gestures: {
                            TapGestureRecognizer:
                                GestureRecognizerFactoryWithHandlers<
                                    TapGestureRecognizer>(
                              () => TapGestureRecognizer(), //constructor
                              (TapGestureRecognizer instance) {
                                instance.onTap = () => print("Tapped");
                              },
                            )
                          },
                          child: SfCartesianChart(
                           zoomPanBehavior:
          ZoomPanBehavior(enablePanning: true, zoomMode: ZoomMode.x),
ghost commented 10 months ago

Hi,

We have validated your query. You can achieve your requirement by using the annotations property in the SfCartesianChart. This property allows you to draw any widget on the chart. In the SfCartesianChart, you can obtain the tapped details by using the onChartTouchInteractionUp callback. You can store the tapped details in a variable to show tapped details. We have prepared a sample code to demonstrate how to display the tapped details in an AlertDialog widget. To display the AlertDialog, you can use the showDialog function in the _showChartDetails function. We have called the _showChartDetails function in the onChartTouchInteractionUp callback to display the AlertDialog. We have also shared a code snippet, sample, and user guide for your reference. Please let us know if you need any further assistance.

UG,

https://help.syncfusion.com/flutter/cartesian-charts/annotations#chart-with-watermark

Code Snippet:

import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyChart(),
    );
  }
}

class MyChart extends StatefulWidget {
  const MyChart({Key? key});

  @override
  State<MyChart> createState() => _MyChartState();
}

double _yPoint = 0;
double _xPoint = 0;

class _MyChartState extends State<MyChart> {
  late List<ChartSampleData> _chartData;

  @override
  void initState() {
    _chartData = <ChartSampleData>[
      ChartSampleData(10, 50),
      ChartSampleData(20, 60),
      ChartSampleData(30, 20),
      ChartSampleData(40, 10),
      ChartSampleData(50, 30),
      ChartSampleData(60, 40),
      ChartSampleData(70, 80),
      ChartSampleData(80, 90),
      ChartSampleData(90, 70),
      ChartSampleData(100, 40),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: SfCartesianChart(
            annotations: const <CartesianChartAnnotation>[
              CartesianChartAnnotation(
                region: AnnotationRegion.chart,
                widget: Text(''),
                coordinateUnit: CoordinateUnit.point,
              ),
            ],
            onChartTouchInteractionUp: (tapArgs) {
              _xPoint = tapArgs.position.dx;
              _yPoint = tapArgs.position.dy;
              _showChartDetails(context);
            },
            primaryXAxis: NumericAxis(),
            primaryYAxis: NumericAxis(),
            series: <ChartSeries<ChartSampleData, num>>[
              LineSeries<ChartSampleData, num>(
                dataSource: _chartData,
                xValueMapper: (ChartSampleData sales, _) => sales.x,
                yValueMapper: (ChartSampleData sales, _) => sales.y,
                width: 3,
              ),
            ],
          ),
        ),
      ),
    );
  }

  void _showChartDetails(BuildContext context) {
    showDialog(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text('Chart Point Details'),
          content: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text('X Point: ${_xPoint.toDouble()}'),
              Text('Y Point: ${_yPoint.toDouble()}'),
            ],
          ),
          actions: [
            TextButton(
              onPressed: () {
                Navigator.of(context).pop();
              },
              child: const Text('OK'),
            ),
          ],
        );
      },
    );
  }
}

class ChartSampleData {
  final num x;
  final num y;

  ChartSampleData(this.x, this.y);
}

Regards, Lokesh P.

chart_523010.zip