speedlight
speedlight

Reputation: 343

Flutter which library provides stacked bar and line chart in same graph?

I would like to create line chart together with stacked bar for flutter. Anyone knows which library can I use? Could not find it in charts_flutter.

Thanks.

Upvotes: 0

Views: 3841

Answers (3)

jbailey
jbailey

Reputation: 327

I took the code from OrdinalComboBarLineChart and replaced it with charts.BarGroupingType.stacked as suggested by speedlight.

I my case I did not need to specify a secondary axis.

/// Example of an ordinal combo chart with two series rendered as stacked bars, and a
/// third rendered as a line.

class OrdinalComboBarLineChart extends StatelessWidget {
  final List<charts.Series> seriesList;
  final bool animate;

  OrdinalComboBarLineChart(this.seriesList, {this.animate});

  factory OrdinalComboBarLineChart.withSampleData() {
    return new OrdinalComboBarLineChart(
      _createSampleData(),
      // Disable animations for image tests.
      animate: false,
    );
  }

  @override
  Widget build(BuildContext context) {
    return new charts.OrdinalComboChart(seriesList,
        animate: animate,
        // Configure the default renderer as a bar renderer.
        defaultRenderer: new charts.BarRendererConfig(
            groupingType: charts.BarGroupingType.stacked),
        // Custom renderer configuration for the line series. This will be used for
        // any series that does not define a rendererIdKey.
        customSeriesRenderers: [
          new charts.LineRendererConfig(
            // ID used to link series to this renderer.
              customRendererId: 'customLine')
        ]);
  }

  /// Create series list with multiple series
  static List<charts.Series<OrdinalSales, String>> _createSampleData() {
    final desktopSalesData = [
      new OrdinalSales('2014', 5),
      new OrdinalSales('2015', 25),
      new OrdinalSales('2016', 100),
      new OrdinalSales('2017', 75),
    ];

    final tableSalesData = [
      new OrdinalSales('2014', 5),
      new OrdinalSales('2015', 25),
      new OrdinalSales('2016', 100),
      new OrdinalSales('2017', 75),
    ];

    final mobileSalesData = [
      new OrdinalSales('2014', 10),
      new OrdinalSales('2015', 50),
      new OrdinalSales('2016', 200),
      new OrdinalSales('2017', 150),
    ];

    return [
      new charts.Series<OrdinalSales, String>(
          id: 'Desktop',
          colorFn: (_, __) => charts.MaterialPalette.blue.shadeDefault,
          domainFn: (OrdinalSales sales, _) => sales.year,
          measureFn: (OrdinalSales sales, _) => sales.sales,
          data: desktopSalesData),
      new charts.Series<OrdinalSales, String>(
          id: 'Tablet',
          colorFn: (_, __) => charts.MaterialPalette.red.shadeDefault,
          domainFn: (OrdinalSales sales, _) => sales.year,
          measureFn: (OrdinalSales sales, _) => sales.sales,
          data: tableSalesData),
      new charts.Series<OrdinalSales, String>(
          id: 'Mobile ',
          colorFn: (_, __) => charts.MaterialPalette.green.shadeDefault,
          domainFn: (OrdinalSales sales, _) => sales.year,
          measureFn: (OrdinalSales sales, _) => sales.sales,
          data: mobileSalesData)
      // Configure our custom line renderer for this series.
        ..setAttribute(charts.rendererIdKey, 'customLine'),
    ];
  }
}

/// Sample ordinal data type.
class OrdinalSales {
  final String year;
  final int sales;

  OrdinalSales(this.year, this.sales);
}

Then I created a flutter app and put the OrdinalComboBarLineChart.withSampleData() as the child of an expanded widget. It worked perfectly.

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';

class HomePage extends StatefulWidget {
  static const String id ='/StackedBarLineExample';
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String myMessageText = '';

  @override
  Widget build(BuildContext context) {
    //print ('logged in screen built');
    return MaterialApp(
      home: DefaultTabController(
        length: 1,
        initialIndex: int.parse(myLastSelectedPhase),
        child: Scaffold(
          appBar: AppBar(
            backgroundColor: Colors.blue,
            bottom: TabBar(
              indicatorColor: Colors.white,
              tabs: [
                Tab(
                    icon: Icon(FontAwesomeIcons.chartBar)
                ),
              ],
            ),
            title: Text('My Graph examples'),
          ),
          body:
          TabBarView(
              children: [
                Padding(
                  padding: EdgeInsets.all(8.0),
                  child: Container(
                    child: Center(
                      child: Column(
                        children: <Widget>[
                          Text(
                            'Stacked bar with line', style: TextStyle(
                              fontSize: 24.0, fontWeight: FontWeight.bold),),
                          Expanded(
                              child: OrdinalComboBarLineChart.withSampleData())
                        ],
                      ),
                    ),
                  ),
                ),
              ]
          ),
        ),
      ),
    );
  }
}

This is the result!

Graph image

Upvotes: 1

speedlight
speedlight

Reputation: 343

By using Ordinal Bar Line Combo Chart, I am able to achieve what I need.

https://google.github.io/charts/flutter/example/combo_charts/ordinal_bar_line.html

Next, change the grouping type to "charts.BarGroupingType.groupedStacked", groupedStacked option with change the bar chart to stacked bar.

Bar chart and line chart has 2 vertical axis, by default, there is only primary axis from the bar chart. You will need to specify secondary axis or else the chart display for stackedbar and line chart will be out.

declare -> static const secondaryMeasureAxisId = 'secondaryMeasureAxisId';

and add "..setAttribute(charts.measureAxisIdKey, 'secondaryMeasureAxisId')," to your linechart.

Lastly, if you have many data, more than 30 like mine. The text under horizontal axis (domain axis) will be overlapping. I cannot find any shortcuts to reduce it. The method I used so far is to declare a new domain axis.

Under build:

final staticTicks = <charts.TickSpec<String>>[];

if(xxx){
   staticTicks.add(xxx);
}

domainAxis: new charts.OrdinalAxisSpec(
          tickProviderSpec:
          new charts.StaticOrdinalTickProviderSpec(staticTicks)),

Upvotes: 0

Anthony Sette
Anthony Sette

Reputation: 837

This seems to be the highest rated package for flutter that can handle both graph types. Be careful with questions like this on Stack Overflow though because it is considered a question of opinion.

flutter_charts: https://pub.dev/packages/flutter_charts

Upvotes: 0

Related Questions