syncfusion/flutter-examples

Having multiple charts bugs the X Axis

salmantln opened this issue · 1 comments

Bug description

Hi I am having the following issue. The chart is not always showing the right data when switching the intervals.
I am using a segment button where

What my goal is to have different x-axis is that every chart segment would have a different. but as seen in the video, unless you hot reload the app, the x-axis is not showing properly.

Steps to reproduce

1, use a hive DB
2, use the given code

Code sample

Code sample
import 'package:fasting_app/data/weight_data.dart';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:intl/intl.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:hive/hive.dart';

class ChartPage extends StatefulWidget {
  @override
  _ChartPageState createState() => _ChartPageState();
}

class _ChartPageState extends State<ChartPage> {
  int _selectedIndex = 0; // Index for segmented control
  late Box<WeightData> _weightDataBox; // Hive box for weight data
  List<WeightData> _weightDataList = []; // List to hold fetched data

  @override
  void initState() {
    super.initState();
    _weightDataBox = Hive.box<WeightData>('weightData');
    _fetchData();
  }

  void _fetchData() {
    setState(() {
      _weightDataList = _weightDataBox.values.toList();
    });
  }

  void _saveData(DateTime date, double weight) {
    var newData = WeightData(date, weight);
    _weightDataBox.add(newData);
    _fetchData();
  }

  Widget _buildChart(DateTime startDate, DateTime endDate, DateTime minimum, DateTime maximum ) {
    List<WeightData> filteredData = _weightDataList
        .where((data) =>
            data.date.isAfter(startDate.subtract(const Duration(days: 1))) &&
            data.date.isBefore(endDate.add(const Duration(days: 1))))
        .toList();

    DateTimeIntervalType intervalType;
    double interval;
    int autoScrollingDelta;
    bool enablePanning;
    // DateTime minimum;
    // DateTime maximum;
    switch (_selectedIndex) {
      case 0: // Weekly
        intervalType = DateTimeIntervalType.days;
        interval = 1;
        autoScrollingDelta = 7;
        enablePanning = true;
        break;
      case 1: // Monthly
        intervalType = DateTimeIntervalType.days;
        interval = 1; // Show weekly intervals within a month
        autoScrollingDelta = 7;
        enablePanning = true;
        break;
      case 2: // Yearly
        intervalType = DateTimeIntervalType.months;
        interval = 1;
        autoScrollingDelta = 12;
        enablePanning = false;
        break;
      default:
        enablePanning = false;
        intervalType = DateTimeIntervalType.days;
        interval = 1;
        autoScrollingDelta = 1;
    }

    return SfCartesianChart(
      zoomPanBehavior: ZoomPanBehavior(enablePanning: enablePanning),
      primaryYAxis: const NumericAxis(
        labelStyle: TextStyle(
          fontFamily: 'Helvetica Neue',
        ),
        opposedPosition: true,
      ),
      primaryXAxis: DateTimeAxis(
        majorGridLines: const MajorGridLines(width: 0),
        dateFormat: _getDateFormat(intervalType),
        intervalType: intervalType,
        interval: interval,
        minimum: minimum,
        maximum: maximum,
        labelStyle: const TextStyle(
          fontFamily: 'Helvetica Neue',
        ),
        autoScrollingDelta: autoScrollingDelta,
        edgeLabelPlacement: EdgeLabelPlacement.none,
      ),
      series: <CartesianSeries>[
        LineSeries<WeightData, DateTime>(
          dataLabelSettings: const DataLabelSettings(
            isVisible: true,
            textStyle: TextStyle(
              fontFamily: 'Helvetica Neue',
            ),
          ),
          color: const Color(0xFFfdb400),
          dataSource: filteredData,
          xValueMapper: (WeightData data, _) => data.date,
          yValueMapper: (WeightData data, _) => data.weight,
          markerSettings: const MarkerSettings(
            isVisible: true,
            width: 10,
            height: 10,
          ),
        ),
      ],
    );
  }

  DateFormat _getDateFormat(DateTimeIntervalType intervalType) {
    switch (intervalType) {
      case DateTimeIntervalType.days:
        return DateFormat('E\nd\nMMM'); // Day of week, day of month, and month
      case DateTimeIntervalType.months:
        return DateFormat('MMM\nyyyy'); // Month and year
      default:
        return DateFormat('E\nd\nMMM'); // Default to daily format
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Weight Tracker'),
      ),
      body: Column(
        children: [
          const SizedBox(height: 20),
          CupertinoSlidingSegmentedControl(
            children: {
              0: const Text('Weekly'),
              1: const Text('Monthly'),
              2: const Text('Yearly'),
            },
            onValueChanged: (index) {
              setState(() {
                _selectedIndex = index!;
              });
            },
            groupValue: _selectedIndex,
          ),
          const SizedBox(height: 20),
          Expanded(
            child: IndexedStack(
              index: _selectedIndex,
              children: [
                _buildChart(
                  DateTime.now().subtract(const Duration(days: 6)), // Weekly
                  DateTime.now(),
                  DateTime.now(),
                    DateTime.now().subtract(const Duration(days: 6))
                ),
                _buildChart(
                  DateTime.now().subtract(const Duration(days: 29)), // Monthly
                  DateTime.now(),
                    DateTime.now().subtract(const Duration(days: 29)), // Monthly
                  DateTime.now(),
                ),
                _buildChart(
                  DateTime.now().subtract(const Duration(days: 364)), // Yearly
                  DateTime.now(),
                   DateTime.now().subtract(const Duration(days: 364)), // Yearly
                  DateTime.now(),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

screen3
screen2
screen1

Screen_Recording_20240708_114245.mp4
Screen_Recording_20240708_121942.mp4

Stack Traces

Stack Traces
[Add the Stack Traces here]
no error, just a bug

On which target platforms have you observed this bug?

Android

Flutter Doctor output

Doctor output
[√] Flutter (Channel stable, 3.19.6, on Microsoft Windows [Version 10.0.22631.3810], locale en-NL)
    • Flutter version 3.19.6 on channel stable at C:\flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 54e66469a9 (3 months ago), 2024-04-17 13:08:03 -0700
    • Engine revision c4cd48e186
    • Dart version 3.3.4
    • DevTools version 2.31.1

[√] Windows Version (Installed version of Windows is version 10 or higher)

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
    • Android SDK at C:\Users\Salman.DESKTOP-84TBD8H\AppData\Local\Android\Sdk
    • Platform android-34, build-tools 34.0.0
    • ANDROID_HOME = C:\Users\Salman.DESKTOP-84TBD8H\AppData\Local\Android\Sdk
    • Java binary at: C:\Program Files\Android\Android Studio2\jbr\bin\java
    • Java version OpenJDK Runtime Environment (build 17.0.10+0--11609105)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.6.5)
    • Visual Studio at C:\Program Files\Microsoft Visual Studio\2022\Community
    • Visual Studio Community 2022 version 17.6.33829.357
    • Windows 10 SDK version 10.0.22000.0

[!] Android Studio (version 2022.3)
    • Android Studio at C:\Program Files\Android\Android Studio1
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    X Unable to determine bundled Java version.
    • Try updating or re-installing Android Studio.

[√] Android Studio (version 2024.1)
    • Android Studio at C:\Program Files\Android\Android Studio2
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 17.0.10+0--11609105)

[√] IntelliJ IDEA Ultimate Edition (version 2022.2)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA 2022.2
    • Flutter plugin version 76.1.1
    • Dart plugin version 222.4582

[√] VS Code (version 1.91.0)
    • VS Code at C:\Users\Salman.DESKTOP-84TBD8H\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.92.0

[√] Connected device (4 available)
    • SM G986B (mobile) • R5CN20NVVZK • android-arm64  • Android 13 (API 33)
    • Windows (desktop) • windows     • windows-x64    • Microsoft Windows [Version 10.0.22631.3810]
    • Chrome (web)      • chrome      • web-javascript • Google Chrome 126.0.6478.127
    • Edge (web)        • edge        • web-javascript • Microsoft Edge 126.0.2592.87

[√] Network resources
    • All expected network resources are available.

Hi @salmantln,

We have analyzed your query and were able to replicate the reported hot loading issue while using the IndexedStack to switch between and display the appropriate chart views (weekly, monthly, yearly) based on the _selectedIndex. This is because IndexedStack shows only one child based on _selectedIndex without automatic updates, requiring explicit state management to maintain accurate x-axis labels. To resolve this issue, we suggest using the Builder instead of IndexedStack. The Builder widget updates its child widgets dynamically whenever _selectedIndex changes, ensuring that _buildChart reflects the correct interval parameters for accurate x-axis labels. We have shared a modified code snippet, output, and test sample for your reference.

Code Snippet:

@override

  Widget build(BuildContext context) {

    return Scaffold(

      body: Column(

        children: [

          const SizedBox(height: 20),

          CupertinoSlidingSegmentedControl<int>(

            children: const {

              0: Text('Weekly'),

              1: Text('Monthly'),

              2: Text('Yearly'),

            },

            onValueChanged: (index) {

              setState(() {

                _selectedIndex = index!;

              });

            },

            groupValue: _selectedIndex,

          ),

          const SizedBox(height: 20),

          Expanded(

            child: Builder(

              builder: (context) {

                if (_selectedIndex == 0) {

                  return _buildChart(

                      DateTime.now().subtract(const Duration(days: 6)),

                      DateTime.now());

                } else if (_selectedIndex == 1) {

                  return _buildChart(

                      DateTime.now().subtract(const Duration(days: 29)),

                      DateTime.now());

                } else {

                  return _buildChart(

                      DateTime.now().subtract(const Duration(days: 364)),

                      DateTime.now());

                }

              },

            ),

          ),

        ],

      ),

    );

  }

}

Screenshot:
gh861

If you are still experiencing the issue, we kindly ask that you try replicating the reported issue in the test sample attached below. Please let us know so that we can assist you more effectively.

Regards,

Preethika Selvam.
gh861.zip