DEV Community

Cover image for Customize Flutter Stock Charts Easily: Add Timeframes, Trendlines & More
Lucy Muturi for Syncfusion, Inc.

Posted on • Originally published at syncfusion.com on

Customize Flutter Stock Charts Easily: Add Timeframes, Trendlines & More

TL;DR: Learn how to customize Flutter Stock Charts by adding technical indicators, switching chart types, applying trendlines, and enabling range selectors. This guide helps developers build interactive and insightful financial dashboards.

Want to build a Flutter-based trading dashboard or stock analysis tool? This guide shows you how to create a fully interactive Flutter Stock Chart with watchlist, indicators, and trendlines, perfect for fintech apps or personal investment tools.

Stock Chart: Functionality logics of Stock Chart sample

The Flutter Stock Chart Sample is a powerful tool designed to help developers and users track and analyze stock data seamlessly. With a wide range of customization options, this sample enables efficient stock monitoring, trend visualization, and personalized analysis. In this guide, we’ll walk through each feature and how it enhances the stock chart experience.

Flutter Stock Chart Sample


Flutter Stock Chart Sample

Features of a Stock Chart

Let’s explore each feature of the Stock Chart one by one in detail.

1. Watchlist

The Watchlist feature allows users to organize and manage their favorite stocks for quick access and monitoring.

Create a new Watchlist

Users can create personalized watchlists by selecting the Add Watchlist option. A dialog prompts for a name, and upon confirmation, the new watchlist is created using the StockChartProvider. Selected stocks are then added to the newly created list.

Widget _buildPopupMenuButton(
  BuildContext context,
  StockChartProvider provider,
  List<Watchlist> watchlists,
  Watchlist? selectedWatchlist,
) {
  return PopupMenuButton<Watchlist>(
    onSelected: (Watchlist watchlist) {
      if (watchlist.id == 'Add Watchlist') {
        switch (deviceType(context)) {
          case DeviceType.mobile:
            Navigator.push(
              context,
              MaterialPageRoute(
                builder: (BuildContext context) {
                  return CreateWatchlistDialog(
                    defaultStocks: widget.defaultStocks,
                  );
                },
              ),
            );
            break;
          case DeviceType.desktop:
            _showCreateWatchlistDialog(context);
            break;
        }
      } else {
        provider.selectedWatchlist = watchlist;
      }
    },
    . . .
  );
}

Widget _buildCreateButton() {
  return TextButton(
    onPressed: _handleCreateButtonPressed,
    child: Text(
      'Create',
    ),
  );
}

void _handleCreateButtonPressed() {
  if (_nameController.text.isNotEmpty) {
    _createNewWatchlist(context);
  }
}

void _createNewWatchlist(BuildContext context) {
  if (_nameController.text.isEmpty) {
    return;
  }
  final StockChartProvider provider = Provider.of<StockChartProvider>(context, listen: false);

  // Create new watchlist.
  final String newWatchlistName = _nameController.text.trim();
  provider.addWatchlist(newWatchlistName);

  // Get the newly created watchlist.
  final Watchlist newWatchlist = provider.watchlists.last;

  // Add selected stocks to the new watchlist.
  for (final Stock stock in _selectedStocks) {
    provider.addStockToWatchlist(stock, newWatchlist);
  }

  // Notify that the watchlist has been updated.
  provider.isWatchListAdded = !provider.isWatchListAdded;

  // Close dialog.
  Navigator.of(context).pop();
}
Enter fullscreen mode Exit fullscreen mode

Adding a new Watchlist


Adding a new Watchlist

Add stocks to Watchlist

Users can select multiple stocks and add them to one or more watchlists in a single action. The UI responds instantly, reflecting the changes without delay.

Behind the scenes, the implementation fetches the selected watchlists and stocks and updates each relevant watchlist by adding new entries. As this update occurs, the application state is refreshed, and listeners are notified, ensuring the UI stays in sync and accurately reflects the changes. Once the update is complete, the confirmation dialog closes, delivering a smooth user experience.

void _addStocksToWatchlists(BuildContext context) {
  final StockChartProvider provider = Provider.of<StockChartProvider>(context, listen: false);

  // Get selected watchlists.
  final List<String> selectedWatchlistIds =
      _selectedWatchlists.entries
          .where((MapEntry<String, bool> entry) => entry.value)
          .map((MapEntry<String, bool> entry) => entry.key)
          .toList();

  // Add each selected stock to each selected watchlist.
  for (final String watchlistId in selectedWatchlistIds) {
    final Watchlist watchlist = provider.watchlists.firstWhere(
      (Watchlist watchlist) => watchlist.id == watchlistId,
    );
    for (final Stock stock in _selectedStocks) {
      provider.addStockToWatchlist(stock, watchlist);
    }
  }

  // Notify that watchlist has been updated.
  provider.isWatchListAdded = !provider.isWatchListAdded;

  // Close dialog.
  Navigator.of(context).pop();
}

void addStockToWatchlist(
  Stock stock,
  Watchlist watchlist, {
  bool isNotify = true,
}) {
  watchlist.addStock(stock);
  stockData[stock]?.isFavorite = true;
  if (isNotify) {
    notifyListeners();
  }
}
Enter fullscreen mode Exit fullscreen mode

Adding stocks to the Watchlist


Adding stocks to the Watchlist

Edit and delete the Watchlist in the Stock Chart

Managing your watchlists just got easier. This feature lets you edit or delete watchlists directly from the menu icon, so you can keep your stock tracking organized and up to date with minimal effort.

Edit Watchlist

With the Edit Watchlist option, you can quickly update the name and stocks in any existing watchlist. When you tap the Edit button, the _showEditWatchlistDialog method opens a dialog preloaded with your selected watchlist’s data. You can rename the list or adjust the stock selections in one place.

Once you’re done editing, the _editNewWatchlist method confirms the changes. If the new name is valid, it updates the watchlist and reflects stock additions instantly. These updates are handled by the StockChartProvider, which triggers a UI rebuild so your changes appear right away, and no extra reloads are needed. It’s a seamless experience designed to keep your workflow smooth and efficient.

/// Shows the edit watchlist dialog.
void _showEditWatchlistDialog(BuildContext context, Watchlist watchlist) {
  final StockChartProvider provider = context.read<StockChartProvider>();

  showDialog<void>(
    context: context,
    builder: (BuildContext context) {
      return EditWatchlistDialog(
        defaultStocks: provider.stockData,
        selectedWatchlist: watchlist,
      );
    },
  );
}

Widget _buildEditButton() {
  return TextButton(
    onPressed: _handleEditButtonPressed,
    child: Text(
      'Edit',
    ),
  );
}

void _handleEditButtonPressed() {
  if (_nameController.text.isNotEmpty) {
    _editNewWatchlist(context);
  }
}

void _editNewWatchlist(BuildContext context) {
  if (_nameController.text.isEmpty) {
    return;
  }

  final StockChartProvider provider = context.read<StockChartProvider>();

  for (final Stock stock in _selectedStocks) {
    provider.addStockToWatchlist(stock, widget.selectedWatchlist);
  }

  if (_nameController.text != widget.selectedWatchlist.name) {
    widget.selectedWatchlist.name = _nameController.text;
  }

  provider.isWatchListAdded = !provider.isWatchListAdded;
  Navigator.of(context).pop();
}
Enter fullscreen mode Exit fullscreen mode

Delete Watchlist

This feature helps you keep your watchlists clean and relevant. When you choose the Delete option, a confirmation dialog appears to ensure the action is intentional, preventing the accidental loss of important data.

Once confirmed, the _showDeleteWatchlistDialog method handles the deletion. The removeWatchlist method from the provider takes care of removing the watchlist and updating the app state. If the deleted watchlist was currently selected, the selection and favorites are reset automatically, keeping the sample consistent and up to date without any manual steps.

/// Shows the delete watchlist confirmation dialog.
void _showDeleteWatchlistDialog(BuildContext context, Watchlist watchlist) {
  showDialog<void>(
    context: context,
    builder: (BuildContext context) {
      return AlertDialog(
        actions: [
          TextButton(
            onPressed: () {
              context.read<StockChartProvider>().removeWatchlist(
                watchlist.id,
              );
              Navigator.pop(context);
            },
            child: Text(
              'Delete'
            ),
          ),
        ],
      );
    },
  );
}

void removeWatchlist(String id) {
  _watchlists.removeWhere((Watchlist watchlist) => watchlist.id == id);
  if (_selectedWatchlist?.id == id) {
    _removeFavorites();
    _updateFavoritesAfterRemove();
    _selectedWatchlist = _watchlists.isNotEmpty ? _watchlists.first : null;
  }
  notifyListeners();
}
Enter fullscreen mode Exit fullscreen mode

Editing and deleting watchlists in the Flutter Stock Chart


Editing and deleting watchlists in the Flutter Stock Chart

2. Custom Timeframe selection in the Stock Chart

Want to explore stock trends over the last 3 months, 5 months, or even a full year? You can do that in a click. But if you’re looking for something more specific, say, a custom date range, you’re in control.

Just use the SfDateRangePicker widget to select the exact dates you’re interested in. As soon as you pick a range, the _handleSelectionChanged method kicks in to capture your selection. Then, when you hit the Apply button, your chosen timeframe is validated, and the stock chart updates instantly to reflect the new data.

It’s that simple. Whether you’re analyzing short-term movements or long-term trends, the chart adapts to your needs, giving you the insights you want, when you want them.

List<DateTime?> pickedDates = [null, null];

SfDateRangePicker(
  onSelectionChanged: _handleSelectionChanged,
),

void _handleSelectionChanged(DateRangePickerSelectionChangedArgs args) {
  setState(() {
    pickedDates[0] = args.value.startDate;
    pickedDates[1] = args.value.endDate;
  });
}

Widget _buildAddButton() {
  return TextButton(
    onPressed: () => _handleApplyButtonPressed(context),
    child: Text(
      'Apply',
    ),
  );
}

void _handleApplyButtonPressed(BuildContext context) {
  if (pickedDates.isNotEmpty &&
      pickedDates[0] != null &&
      pickedDates[1] != null) {
    widget.onRangeDateSelected(pickedDates[0]!, pickedDates[1]!);
    Navigator.pop(context);
  }
}
Enter fullscreen mode Exit fullscreen mode

The _ updateDateRange method is used to update the chart timeframe from the dropdown menu using default values such as 3M, 5M, and 1Y, ensuring that stock data is accurately presented based on the user’s selected timeframe.

void _updateDateRange(BuildContext context, DateRange selectedDateRange) {
  final DateTime now = DateTime(2025);
  final StockChartProvider provider = context.read<StockChartProvider>();

  primaryChartAxisController?.visibleMaximum = now;

  switch (selectedDateRange) {
    case DateRange.oneMonth:
      primaryChartAxisController?.visibleMinimum = DateTime(
        now.year,
        now.month - 1,
        now.day,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime(
          now.year,
          now.month - 1,
          now.day,
        );
        axisController?.visibleMaximum = now;
      }
      break;

    case DateRange.oneYear:
      primaryChartAxisController?.visibleMinimum = DateTime(
        now.year - 1,
        now.month,
        now.day,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime(
          now.year - 1,
          now.month,
          now.day,
        );
        axisController?.visibleMaximum = now;
      }
      break;

    case DateRange.customRange:
      break;

    case DateRange.all:
      primaryChartAxisController?.visibleMinimum = DateTime.parse(
        provider.viewModel.dataCollections.first.date,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime.parse(
          provider.viewModel.dataCollections.first.date,
        );
        axisController?.visibleMaximum = now;
      }
      break;
  }
}
Enter fullscreen mode Exit fullscreen mode

Timeframe selection in Flutter Stock Chart


Timeframe selection in Flutter Stock Chart

3. Multiple indicators on Stock Chart

Want to go beyond just price movements? You can! With the indicator feature, you get powerful tools to analyze stock performance more thoroughly, thanks to two types of indicators: overlay and underlay.

Overlay indicators

These appear right on the main chart, like the Simple Moving Average (SMA), giving you instant visual insights. You can add them easily using a dropdown menu, and they’re managed through the StockChartProvider.

SfCartesianChart(
  indicators: _buildOverlayIndicators(viewModel),
),

List<TechnicalIndicator<Data, DateTime>> _buildOverlayIndicators(
  StockChartViewModel viewModel,
) {
  final List<TechnicalIndicator<Data, DateTime>> indicators = [];
  final StockChartProvider provider = context.read<StockChartProvider>();

  for (final IndicatorInstance<OverlayIndicatorType> indicatorInstance
      in viewModel.overlayIndicators) {
    final OverlayIndicatorType indicator = indicatorInstance.indicatorType;
    final bool hide =
        provider.overlayIndicatorHandlerList[indicatorInstance.id]!;

    switch (indicator) {
      case OverlayIndicatorType.sma:
        indicators.add(
          SmaIndicator<Data, DateTime>(
            isVisible: !hide,
            animationDuration: 0.0,
            seriesName: 'Price',
            yAxisName: 'primaryYAxis',
          ),
        );
        break;
      . . .
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Overlay indicators in Flutter Stock Chart


Overlay indicators in Flutter Stock Chart

Underlay indicators

These are displayed below the main chart and are perfect for tracking momentum or volume trends. They’re dynamically rendered and updated using state selectors, ensuring smooth performance even with complex data.

Widget _buildChartView(StockChartViewModel viewModel, BuildContext context) {
  final bool showMainChartXAxis = viewModel.underlayIndicators.isEmpty;
  return Selector<StockChartProvider, bool>(
    selector: (BuildContext context, StockChartProvider provider) {
      return provider.isTrendlineTypeChanged;
    },
    builder: (BuildContext context, bool value, Widget? child) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          // Main chart with overlay indicators.
          Selector<StockChartProvider, bool>(
            selector: (BuildContext context, StockChartProvider provider) {
              return provider.isOverlayPopupUpdate;
            },
            builder: (BuildContext context, bool value, Widget? child) {
              return StockPrimaryCartesianChart(
                viewModel: viewModel,
                showXAxis: showMainChartXAxis,
              );
            },
          ),
          ..._buildUnderlayIndicatorCharts(context, viewModel),
        ],
      );
    },
  );
}

List<Widget> _buildUnderlayIndicatorCharts(
  BuildContext context,
  StockChartViewModel viewModel,
) {
  final StockChartProvider provider = context.read<StockChartProvider>();

  return List<Widget>.generate(viewModel.underlayIndicators.length, (index) {
    return _buildUnderLineIndicatorChart(provider, viewModel, index);
  });
}

Widget _buildUnderLineIndicatorChart(
  StockChartProvider provider,
  StockChartViewModel viewModel,
  int index,
) {
  final bool isLastIndicator =
      index == viewModel.underlayIndicators.length - 1;

  final IndicatorInstance<UnderlayIndicatorType> indicatorInstance =
      viewModel.underlayIndicators[index];

   return Expanded(
    child: Selector<StockChartProvider, bool>(
      selector: (BuildContext context, StockChartProvider provider) =>
          provider.isUnderlayIndicatorPopupUpdate,
      builder: (BuildContext context, bool value, Widget? child) {
        return UnderlayIndicatorChartAndPopup(
          indicatorInstance: indicatorInstance,
          viewModel: viewModel,
          index: index,
          showIndicator:
              !provider.underlayIndicatorHandlerList[indicatorInstance.id]!,
          isLastIndicator: isLastIndicator,
        );
      },
    ),
  );
}
Enter fullscreen mode Exit fullscreen mode

Underlay indicators in Flutter Stock Chart


Underlay indicators in Flutter Stock Chart

Floating pop-up menu for indicators

Managing your chart indicators shouldn’t slow you down, and it doesn’t. With a floating pop-up menu, you can quickly toggle visibility or remove indicators without ever leaving the chart view.

This menu appears only when indicators are active, thanks to a smart implementation using a Stack. Each indicator listed in the pop-up comes with visibility and close icons, so you can show, hide, or remove them with a single tap. Behind the scenes, provider methods handle these actions, while state selectors ensure the chart and pop-up update instantly and smoothly.

It’s a seamless experience designed to keep your focus on the data, not the controls.

Widget _buildChartView(StockChartViewModel viewModel, BuildContext context) {
  final bool showMainChartXAxis = viewModel.underlayIndicators.isEmpty;
  final StockChartProvider provider = context.read<StockChartProvider>();
  final DateTime endDate = DateTime(2025);

  provider.chartRangeController ??= RangeController(
    start: _startRange(provider, endDate),
    end: endDate,
  );

  return Selector<StockChartProvider, bool>(
    selector: (BuildContext context, StockChartProvider provider) {
      return provider.isTrendlineTypeChanged;
    },
    builder: (BuildContext context, bool value, Widget? child) {
      return Selector<StockChartProvider, bool>(
        selector: (BuildContext context, StockChartProvider provider) {
          return provider.isOverlayPopupUpdate;
        },
        builder: (BuildContext context, bool value, Widget? child) {
          return Stack(
            children: [
              StockPrimaryCartesianChart(
                viewModel: viewModel,
                showXAxis: showMainChartXAxis,
              ),
              if (context
                  .read<StockChartProvider>()
                  .overlayIndicators
                  .isNotEmpty)
                OverlayIndicatorPopup(
                  indicatorTypes: context
                      .read<StockChartProvider>()
                      .overlayIndicators,
                ),
              if (context
                  .read<StockChartProvider>()
                  .stockTrendlines
                  .isNotEmpty)
                OverlayTrendlinePopup(
                  trendlineTypes: context
                      .read<StockChartProvider>()
                      .stockTrendlines,
                ),
            ],
          );
        },
      );
    },
  );
}
Enter fullscreen mode Exit fullscreen mode

Floating popup menu for toggling the visibility and removing the indicators


Floating popup menu for toggling the visibility and removing the indicators

4. Trendlines in Stock Chart

You can add trendlines, like linear or moving average, right onto your stock chart to help visualize long-term trends.

You control everything through a simple dropdown. When you add or remove a trendline, the StockChartProvider keeps track of its type and visibility. The view model updates instantly, and the _buildTrendlines method reads the active trendlines to generate the right objects.

These trendlines are then passed to the chart’s trendlines property, allowing them to render seamlessly alongside your main stock series. It’s a smooth, dynamic way to enhance your analysis without cluttering the interface.

CandleSeries<Data, DateTime> _buildCandleSeries(
  StockChartViewModel viewModel,
) {
  return CandleSeries<Data, DateTime>(
    trendlines: _buildTrendlines(viewModel),
  );
}

List<Trendline> _buildTrendlines(StockChartViewModel viewModel) {
  final List<Trendline> trendlines = <Trendline>[];
  final StockChartProvider provider = context.read<StockChartProvider>();

  for (final TrendlineInstance<TrendlineType> trendlineInstance
      in viewModel.stockTrendlines) {
    trendlines.add(
      Trendline(
        type: trendlineInstance.trendlineType,
        isVisible: !provider.trendlineHandlerList[trendlineInstance.id]!,
      ),
    );
  }
  return trendlines;
}
Enter fullscreen mode Exit fullscreen mode

Visualize stock trends with trendlines in Flutter Stock Chart


Visualize stock trends with trendlines in Flutter Stock Chart

5. Chart types

The stock chart supports multiple types, Area, Candle, Column, and Line, and you can switch between them effortlessly using a dropdown menu.

When you select a different chart type, the selectedSeriesType property updates to reflect your choice. The _buildCartesianSeries method then kicks in, dynamically constructing the right chart series based on your selection. The result? A chart that instantly adapts to your preferred visualization style.

It’s all about giving you the flexibility to analyze data your way.

SfCartesianChart(
  series: [_buildCartesianSeries(viewModel)],
),

CartesianSeries<Data, DateTime> _buildCartesianSeries(
  StockChartViewModel viewModel,
) {
  switch (viewModel.selectedSeriesType) {
    case SeriesType.area:
      return _buildAreaSeries(viewModel);
    case SeriesType.candle:
      return _buildCandleSeries(viewModel);
    case SeriesType.hollowCandle:
    . . .
  }
}

CandleSeries<Data, DateTime> _buildCandleSeries(
  StockChartViewModel viewModel,
) {
  return CandleSeries<Data, DateTime>(
    dataSource: viewModel.dataCollections,
    xValueMapper: (Data data, int index) => DateTime.parse(data.date),
    highValueMapper: (Data data, int index) => data.high,
    lowValueMapper: (Data data, int index) => data.low,
    openValueMapper: (Data data, int index) => data.open,
    closeValueMapper: (Data data, int index) => data.close,
  );
}
Enter fullscreen mode Exit fullscreen mode

Chart types in Flutter Stock Chart


Chart types in Flutter Stock Chart

6. Stock Chart customization settings

You can personalize the chart’s appearance and behavior through the settings panel.

  • Tooltips: Toggle them on or off to show or hide data point details, perfect for decluttering or diving deeper.
  • Y-Axis Type: Switch between numeric and logarithmic scales depending on how you want to interpret price movements.
  • Axis Position: Prefer the Y-axis on the opposite side? You can toggle between standard and opposed positions.
  • Range Selector: Use the slider to zoom into specific timeframes and focus on the data that matters most to you.
SfCartesianChart(
  tooltipBehavior: stockToolTipBehavior(viewModel.chartSettings),
),
Enter fullscreen mode Exit fullscreen mode

Tooltips in the Flutter Stock Chart


Tooltips in the Flutter Stock Chart

SfCartesianChart(
  primaryYAxis: _buildYAxis(context, viewModel.chartSettings),
),

ChartAxis _buildYAxis(BuildContext context, ChartSettings settings) {
  if (settings.logarithmicYAxis) {
    return LogarithmicAxis(
      ...
    );
  } else {
    return NumericAxis(
      ...
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Customize axis type in Flutter Stock Chart


Customize axis type in Flutter Stock Chart

SfCartesianChart(
  primaryYAxis: _buildYAxis(context, viewModel.chartSettings),
),

ChartAxis _buildYAxis(BuildContext context, ChartSettings settings) {
  if (settings.logarithmicYAxis) {
    return LogarithmicAxis(
      opposedPosition: settings.opposedAxis,
    );
  } else {
    return NumericAxis(
      opposedPosition: settings.opposedAxis,
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Customize axis position in Flutter Stock Chart


Customize axis position in Flutter Stock Chart

SfRangeSelector(
  min: min,
  max: max,  
  controller: provider.chartRangeController,
  dateIntervalType: slider.DateIntervalType.years,
  onChanged: (slider.SfRangeValues values) {
    final DateTime desiredMinDate = _startRange(provider, max);

    for (final DateTimeAxisController? axisController
        in provider.zoomingHandlerList.values) {
      axisController?.visibleMinimum = values.start;
      axisController?.visibleMaximum = values.end;
    }

    if (values.start != desiredMinDate || values.end != max) {
      provider.enableReset = true;
    } else {
      provider.enableReset = false;
    }
  },
 . . .
),
Enter fullscreen mode Exit fullscreen mode

7. Chart synchronization

Zooming and panning actions on the main chart are fully synchronized with the underlay indicator charts, creating a cohesive and intuitive analysis experience.

This synchronization is achieved using the onZooming, onZoomStart, and onZoomEnd events in the SfCartesianChart widget. When a zoom or pan action occurs on either chart, the visible range for both charts is updated simultaneously. This is done by iterating through the axis controllers and adjusting their zoomFactor and zoomPosition properties based on the user’s interaction.

The result is a smooth, unified view that keeps all chart elements aligned and responsive.

onZooming: (ZoomPanArgs zoomingArgs) {
  if (!zoomingArgs.axis!.isVertical) {
    for (final DateTimeAxisController? axisController
        in provider.zoomingHandlerList.values) {
      axisController?.zoomFactor = zoomingArgs.currentZoomFactor;
      axisController?.zoomPosition =
          zoomingArgs.currentZoomPosition;
    }
    if (zoomingArgs.currentZoomFactor == 1 &&
        provider.selectedDateRange == DateRange.all) {
      provider.enableReset = false;
    } else {
      provider.enableReset = true;
    }
  }
},

onZoomStart: (ZoomPanArgs zoomingArgs) {
  if (!zoomingArgs.axis!.isVertical) {
    for (final DateTimeAxisController? axisController
        in provider.zoomingHandlerList.values) {
      axisController?.zoomFactor = zoomingArgs.currentZoomFactor;
      axisController?.zoomPosition =
          zoomingArgs.currentZoomPosition;
    }
    if (zoomingArgs.currentZoomFactor == 1 &&
        provider.selectedDateRange == DateRange.all) {
      provider.enableReset = false;
    } else {
      provider.enableReset = true;
    }
  }
},

onZoomEnd: (ZoomPanArgs zoomingArgs) {
  if (!zoomingArgs.axis!.isVertical) {
    for (final DateTimeAxisController? axisController
        in provider.zoomingHandlerList.values) {
      axisController?.zoomFactor = zoomingArgs.currentZoomFactor;
      axisController?.zoomPosition =
          zoomingArgs.currentZoomPosition;
    }
    if (zoomingArgs.currentZoomFactor == 1 &&
        provider.selectedDateRange == DateRange.all) {
      provider.enableReset = false;
    } else {
      provider.enableReset = true;
    }
  }
},
Enter fullscreen mode Exit fullscreen mode

Synchronization in Flutter Stock Chart


Synchronization in Flutter Stock Chart

8. Stock Chart refresh button

After zooming or panning through stock data, getting back to the original chart view is just a click away. The refresh button resets the chart to its default state, making it easy to start fresh.

This button is implemented as a widget within the StockChartViewer and connects directly with the StockChartProvider. When pressed, it triggers the _updateDateRange function, which recalculates the chart’s visible minimum and maximum range based on the currently selected date range. The result is a clean, default view, ready for your next analysis.

Widget _buildResetButton(BuildContext context) {
  final StockChartProvider provider = context.read<StockChartProvider>();
  return Material(
    shape: const CircleBorder(),
    child: IconButton(
      icon: const Icon(Icons.refresh),
      onPressed: () {
        _updateDateRange(context, provider.selectedDateRange);
        provider.enableReset = false;
      },
    ),
  );
}

void _updateDateRange(BuildContext context, DateRange selectedDateRange) {
  final DateTime now = DateTime(2025);
  final StockChartProvider provider = context.read<StockChartProvider>();
  primaryChartAxisController?.visibleMaximum = now;
  switch (selectedDateRange) {
    case DateRange.oneMonth:
      primaryChartAxisController?.visibleMinimum = DateTime(
        now.year,
        now.month - 1,
        now.day,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime(
          now.year,
          now.month - 1,
          now.day,
        );
        axisController?.visibleMaximum = now;
      }
      break;
    case DateRange.oneYear:
      primaryChartAxisController?.visibleMinimum = DateTime(
        now.year - 1,
        now.month,
        now.day,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime(
          now.year - 1,
          now.month,
          now.day,
        );
        axisController?.visibleMaximum = now;
      }
      break;
    case DateRange.customRange:
      break;
    case DateRange.all:
      primaryChartAxisController?.visibleMinimum = DateTime.parse(
        provider.viewModel.dataCollections.first.date,
      );
      for (final DateTimeAxisController? axisController
          in provider.zoomingHandlerList.values) {
        axisController?.visibleMinimum = DateTime.parse(
          provider.viewModel.dataCollections.first.date,
        );
        axisController?.visibleMaximum = now;
      }
      break;
  }
}
Enter fullscreen mode Exit fullscreen mode

Resetting the Chart using the refresh button


Resetting the Chart using the refresh button

Conclusion

Thanks for reading! In this blog, we have explored the features and functionality of a Stock Chart Sample. This interactive platform allows users to experiment with various stock chart features. By offering customization options, users can tailor the interface to their preferences. Overall, this sample is a versatile tool for exploring the potential of stock charts in a user-friendly manner.

Existing Syncfusion users can access the most recent Essential Studio on the license and downloads page. If you’re new to Syncfusion, we offer a 30-day free trial to test these exciting new features.

You can also contact us through our support forum, support portal, or feedback portal. We are always happy to help you!

Related Blogs

This article was originally published at Syncfusion.com.

Top comments (0)