Charts in Flutter

Suyog Ghinmine
{{classes}} & {{functions}}
5 min readMar 23, 2020

--

By the end of this tutorial, you’ll have sound understanding of working with charts in Flutter, plus you’ll also have a great app with pretty charts all over it.

In this particular article, I’ve focused on Pie chart to avoid writing a tldr article.

Here’s a little preview of all the chart you’ll build:

I am going to be using an external library called charts_flutter. This library is maintained by Google and I guess now you know why I chose this particular library.

(You can read more about it here, but that’s entirely optional).

Step 1:

Create a new Flutter project, wipe out all existing code from the main.dart file. And jump right into the pubspec.yaml file. This is the file that matters a lot when you have dependencies or libraries to import. Without specifying them here, you cannot expect to use them in your project.

In this pubspec.yaml file, under the dependencies, include chart_flutter:

charts_flutter: ^0.6.0

More specifically,

dependencies:  flutter:    sdk: flutter  charts_flutter: ^0.6.0

Make sure the alignments are correct, because yaml files are sensitive to alignments.

Save this file and VS will automatically run the ‘flutter pub get’ command for you.

We are not going to make any further changes to this file, so you might as well close it.

Step 2:

Now that you have the library ready-to-use in your project, let’s import it into our blank main.dart file.

import ‘package:flutter/material.dart’;
import ‘package:charts_flutter/flutter.dart’ as charts;

The second import is for charts, the first one is for material components.

Next, le’s write the basic code to run our app.

For that, start out with a main function:

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

You are bound to get an error at this point, since we haven’t defined a MyApp class. So let’s define a StatefulWidget MyApp.

class MyApp extends StatefulWidget {    @override _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> {    @override Widget build(BuildContext context) {      return MaterialApp(          home: Scaffold(             body: Text('Home'),          ),      );    }
}

When you run this on a simulator or actual device, you should see the word Home printed somewhere in the left corner and that’s perfectly fine for now.

The current screen

What bugs me the most is the debug banner at the corner, so within the MaterialApp call the property debugShowCheckedModeBanner and set it to false.

Step 3:

Now that we have a canvas, let’s start drawing.

First let’s define a class called PieData. Our Pie chart will display time spent on each activity across the day.

class PieData {    String activity;    double time;    PieData(this.activity, this.time);}

Now define a variable _pieData of type List<charts.Series<PieData, String>>. This variable will provide our chart with the necessary data.

Do not forget to initialise it using initState() function to make sure the value is initialised on opening the app.

@override void initState() {    super.initState();    _pieData = List<charts.Series<PieData, String>>();}

Let’s define a function called generateData() : this is where all the data for the Pie chart is going to be rendered from.

generateData(){    var piedata = [        new PieData('Work', 35.8),        new PieData('Eat', 8.3),        new PieData('Commute', 10.8),        new PieData('TV', 15.6),        new PieData('Sleep', 19.2),        new PieData('Other', 10.3),    ];}

The variable pieData is a list of values of PieData. We are going to add this data into our _pieData variable, that we’re going to use later to render the charts.

generateData() {    var piedata = [        new PieData('Work', 35.8),        new PieData('Eat', 8.3),        new PieData('Commute', 10.8),        new PieData('TV', 15.6),        new PieData('Sleep', 19.2),        new PieData('Other', 10.3),    ];    _pieData.add(        charts.Series(            domainFn: (PieData data, _) => data.activity,            measureFn: (PieData data, _) => data.time,            id: 'Time spent',            data: piedata,            labelAccessorFn: (PieData row, _) => '${row.activity}',        ),    );    return _pieData;}

The .add() function called on the _pieData variable does all the trick.

It appends a value of type charts.Series with multiple parameters to the list _pieData.

These parameters are domainFn, measureFn, id, data and labelAccessorFn. There are a few other parameters like colorFn, etc but let’s be focused on the essentials for now.

domainFn: It governs the entity to be measured. In this case, activity.

measureFn: It governs the quantity of the entity to be measured, i.e, time.

id: It’s simply a label for what your graph represents. Let’s just call this ‘Time spent’.

data: This is where all your values from the previous variable go.

labelAccessorFn: This is an optional parameter that defines the behaviour of the labels.

Step 4:

The next step is to use this data and render into a chart. For that, in our build() function, let’s replace the Text widget with the graph.

So change the Scaffold body to:

body: Center(    child: charts.PieChart(    generateData()    ),
),

The charts.PieChart widget takes List<charts.Series<PieData, String>> as a parameter. (Not explicitly PieData and String, but these data types in this case). And our generateData() function returns a value of this type.

Reload your application and your screen changes to:

But there’s still something missing, the charts are pretty much empty and you do not know what’s what. To make sure legends are added to the graph, set another property of the charts.PieChart widget:

defaultRenderer: new charts.ArcRendererConfig(    // arcWidth: 100, //Uncomment for a donut pie chart    arcRendererDecorators: [        new charts.ArcLabelDecorator(        labelPosition: charts.ArcLabelPosition.inside)    ],)

Behold, the pretty pie chart you were promised:

Donut Pie Chart

You can also control the animation duration etc.

Complete code:

import 'package:flutter/material.dart';import 'package:charts_flutter/flutter.dart' as charts;void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override _MyAppState createState() => _MyAppState();}class _MyAppState extends State<MyApp> {
List<charts.Series<PieData, String>> _pieData;
@override void initState() { super.initState(); _pieData = List<charts.Series<PieData, String>>(); }
generateData() { var piedata = [ new PieData('Work', 35.8), new PieData('Eat', 8.3), new PieData('Commute', 10.8), new PieData('TV', 15.6), new PieData('Sleep', 19.2), new PieData('Other', 10.3), ]; _pieData.add( charts.Series( domainFn: (PieData data, _) => data.activity, measureFn: (PieData data, _) => data.time, id: 'Time spent', data: piedata, labelAccessorFn: (PieData row, _) => '${row.activity}', ), ); return _pieData;}@override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( body: Center( child: charts.PieChart( generateData(), animate: true, animationDuration: Duration(seconds: 5), defaultRenderer: new charts.ArcRendererConfig( arcWidth: 100, arcRendererDecorators: [ new charts.ArcLabelDecorator( labelPosition: charts.ArcLabelPosition.inside) ], ), ), ), )
);
}}class PieData { String activity; double time; PieData(this.activity, this.time);}

--

--