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.58k stars 773 forks source link

Invisible StackedColumnSeries with ZoomMode.x not working #1773

Closed DrNiels closed 6 months ago

DrNiels commented 7 months ago

In my app, I want an external source to determine which series are visible. However, when StackedColumnSeries are initially not visible in combination with ZoomMode set to x, an error is thrown.

You can reproduce it with the following code:

import 'package:syncfusion_flutter_charts/charts.dart';

bool detailed = false;

void main() async {
  runApp(
    MaterialApp(
      home: TestChart(),
    ),
  );
}

class TestChart extends StatefulWidget {
  static List<Offset> allData = [
    Offset(0, 0),
    Offset(1, 10),
    Offset(2, 2),
    Offset(3, 13),
    Offset(4, 4),
    Offset(5, 15),
    Offset(6, 6),
    Offset(7, 17),
    Offset(8, 8),
    Offset(9, 19),
    Offset(10, 10),
  ];

  _TestChartState createState() => _TestChartState();
}

class _TestChartState extends State<TestChart> {

  @override
  Widget build(BuildContext context) {
    return SfCartesianChart(
      series: [
        StackedColumnSeries<Offset, num>(
          xValueMapper: (data, _) => data.dx,
          yValueMapper: (data, _) => data.dy,
          dataSource: TestChart.allData,
          initialIsVisible: false,
        ),
      ],
      primaryYAxis: NumericAxis(
        minimum: 0,
        maximum: 20,
      ),
      primaryXAxis: NumericAxis(
        minimum: 0,
        maximum: 10,
      ),
      zoomPanBehavior: ZoomPanBehavior(
        zoomMode: ZoomMode.x,
      ),
    );
  }
}

Starting this example will immediately throw an error:

══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
The following IndexError was thrown during performLayout():
RangeError (index): Index out of range: no indices are valid: 0

The relevant error-causing widget was:
  NumericAxis NumericAxis:org-dartlang-app:/invisible_error.dart:49:21

When the exception was thrown, this was the stack:
dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 297:3     throw_
dart-sdk/lib/_internal/js_dev_runtime/private/js_array.dart 600:7               _get]
packages/syncfusion_flutter_charts/src/charts/series/chart_series.dart 3770:35  [_calculateYRange]
packages/syncfusion_flutter_charts/src/charts/series/chart_series.dart 5667:18  [_calculateYRange]
packages/syncfusion_flutter_charts/src/charts/series/chart_series.dart 6342:18  [_calculateYRange]
packages/syncfusion_flutter_charts/src/charts/series/chart_series.dart 3749:44  [_findVisibleIndexes]
packages/syncfusion_flutter_charts/src/charts/series/chart_series.dart 3668:7   didRangeChange
packages/syncfusion_flutter_charts/src/charts/axis/axis.dart 1977:20            <fn>
packages/flutter/src/rendering/object.dart 2686:51                              <fn>
packages/flutter/src/rendering/object.dart 1097:7                               [_enableMutationsToDirtySubtrees]
packages/flutter/src/rendering/object.dart 2686:7                               invokeLayoutCallback
packages/syncfusion_flutter_charts/src/charts/axis/axis.dart 1975:7             [_calculateRangeAndInterval]
packages/syncfusion_flutter_charts/src/charts/axis/axis.dart 1772:7             performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/syncfusion_flutter_charts/src/charts/base.dart 1961:13                 measureHorizontalAxes
packages/syncfusion_flutter_charts/src/charts/base.dart 1999:5                  performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/syncfusion_flutter_charts/src/charts/base.dart 771:23                  performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/syncfusion_flutter_charts/src/charts/common/core_legend.dart 989:5     performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/shifted_box.dart 239:5                           performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/shifted_box.dart 239:5                           performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/proxy_box.dart 3728:13                           performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/widgets/overlay.dart 968:12                                layoutChild
packages/flutter/src/widgets/overlay.dart 1282:9                                performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/custom_paint.dart 569:11                         performLayout
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/proxy_box.dart 105:21                            <fn>
packages/flutter/src/rendering/object.dart 2575:7                               layout
packages/flutter/src/rendering/box.dart 2389:11                                 layout
packages/flutter/src/rendering/view.dart 195:7                                  performLayout
packages/flutter/src/rendering/object.dart 2414:7                               [_layoutWithoutResize]
packages/flutter/src/rendering/object.dart 1051:17                              flushLayout
packages/flutter/src/rendering/object.dart 1064:14                              flushLayout
packages/flutter/src/rendering/binding.dart 582:5                               drawFrame
packages/flutter/src/widgets/binding.dart 991:13                                drawFrame
packages/flutter/src/rendering/binding.dart 448:5                               [_handlePersistentFrameCallback]
packages/flutter/src/scheduler/binding.dart 1386:7                              [_invokeFrameCallback]
packages/flutter/src/scheduler/binding.dart 1311:9                              handleDrawFrame
packages/flutter/src/scheduler/binding.dart 1034:7                              <fn>
dart-sdk/lib/_internal/js_dev_runtime/private/isolate_helper.dart 48:11         internalCallback

The following RenderObject was being processed when the exception was fired: RenderNumericAxis#e1c3a relayoutBoundary=up3 NEEDS-LAYOUT NEEDS-PAINT:
  creator: NumericAxis ← CartesianAxes ← CartesianChartArea ← KeyedSubtree-[GlobalKey#b97b8] ←
    _LegendLayoutHandler ← LegendLayout-[GlobalKey#80c20] ← Padding ← Padding ← DecoratedBox ←
    Container ← RepaintBoundary ← SfCartesianChart ← ⋯
  parentData: offset=Offset(0.0, 0.0) (can use size)
  constraints: BoxConstraints(0.0<=w<=1874.8, 0.0<=h<=933.0)
  size: MISSING
This RenderObject has no descendants.
════════════════════════════════════════════════════════════════════════════════════════════════════

Using a regular ColumnSeries instead of a StackedColumnSeries does not throw the error, nor is it thrown if I remove the zoom mode setting, so this may be a specific combination causing the issue.

I use version 25.1.35 of syncfusion_flutter_charts

Output of flutter doctor:

[√] Android toolchain - develop for Android devices (Android SDK version 34.0.0-rc4)
[√] Chrome - develop for the web
[√] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.8.6)
[√] Android Studio (version 2021.2)
[√] VS Code, 64-bit edition (version 1.87.2)
[√] Connected device (3 available)
[√] Network resources

I'm currently using Flutter in Web.

ghost commented 6 months ago

Hi @DrNiels,

We can reproduce the reported issue regarding the ‘Exception thrown when setting initialIsVisible to false in the StackedColumnSeries along with zooming’ at our end. We will fix and include this issue in our upcoming weekly patch release, which is expected to be rolled out on April 16, 2024. We will notify you once it has been rolled out. We appreciate your patience until then.

Regards, Lokesh P.

ghost commented 6 months ago

Hi @DrNiels,

We would like to let you know that the reported issue is fixed and rolled out in our patch release. We kindly request you to upgrade the syncfusion_flutter_charts package to the latest version below.

Version: https://pub.dev/packages/syncfusion_flutter_charts/versions/25.1.40

Root cause: Tried to access the stacked series y-values when the series visibility is false, and the zoom mode is 'x'. So, null exceptions occur when trying to calculate the y-axis range.

If you have any further queries, please feel free to reach out to us.

Regards, Lokesh P.

DrNiels commented 6 months ago

It's working now, thank you!