Working with Flutter graphs
By: Naveen Renati
Tags: Graph, Flutter, App Development, Flutter App Development, Flutter Ui

Getting Started

Let's create a flutter project and make a stateful class start with.

Implementation:

We will create a new dart file and name it Home and make it a Stateful class. Change your existing main.dart file as shown below

Let’s add a package called charts_flutter in pubspec and run flutter pub get.

Add the dependency

dependencies:

flutter:

sdk: flutter

charts_flutter: ^0.10.0

Run flutter packages get in the root directory of your app.

Import in Home class

import 'package:flutter/material.dart';

import 'package:charts_flutter/flutter.dart' as charts;

Now let’s take a look at our sample JSON data to plot the graph

var response = {

"count": 30,

"next": null,

"previous": null,

"results": [

{"date": "2017-06-01T00:00:00+05:30", "price": "2848.55"},

{"date": "2017-07-01T00:00:00+05:30", "price": "2887.06"},

{"date": "2017-08-01T00:00:00+05:30", "price": "2984.83"},

]

};

Let’s create a model class for the above JSON response.

We need a simple class that helps in plotting the graph which contains two variables. I’ll be adding this in Home right after closing the homeclass.

class _GraphData {

final String date;

final String price;



_GraphData(this.date, this.price);

}

Now that we have the data and model class ready let’s start with the UI in the Home class. Before starting with UI lets create some variables which we need later in the process

List<_GraphData> _stockGraph = [];

List<GraphTimeData> graphData;



var rate, date;



NumberFormat simpleCurrencyFormat =

NumberFormat.simpleCurrency(locale: 'en_IN', decimalDigits: 2);



var stockImage =

'https://gumlet.assettype.com/swarajya%2F2019-05%2F4bbec1ee-80cf-460b-a1f2-ff388ed7eeea%2F576px_ITC_Limited_Logo_svg.png?auto=format&q=35&w=1200&rect=0,276,576,324';

The simpleCurrencyFormat is for the rupee symbol and limit to 2 decimal points.

Add a scaffold as a parent widget and give background color and add an appbar.

backgroundColor: Colors.black,

appBar: AppBar(

backgroundColor: Colors.black,

title: Row(

crossAxisAlignment: CrossAxisAlignment.center,

mainAxisAlignment: MainAxisAlignment.center,

children: [

Container(

width: 50,

height: 50,

color: Colors.white,

child: Image.network('$stockImage')),

SizedBox(

width: 10,

),

Text('Stock Price Growth'),

],

),

centerTitle: true,

),

Let’s add sample data required to plot the graph. We will create a method where we will be setting up the data to the graph.

We need to add sample JSON data. Create a file called JsonData and place the below code

In initState create a function called getGraphData();

void getGraphData() async {

GraphTimeDataList graphList = GraphTimeDataList.fromJson(response);

setState(() {

graphData = graphList.results;

this._stockGraph = _getStockGraphData(graphData);

});

}

}

To the body add a SingleChildScrollView and as a child, we will add a container to give height to the graph. Let’s take a look at the code below

Container(

height: MediaQuery.of(context).size.height * 0.3,

child: charts.TimeSeriesChart(

[

charts.Series<_GraphData, DateTime>(

id: 'Stock Price',

colorFn: (_, __) =>

charts.ColorUtil.fromDartColor(Colors.green),

domainFn: (_GraphData row, _) =>

DateTime.tryParse(row.date),

measureFn: (_GraphData row, _) => double.parse(row.price),

data: _stockGraph,

),

],

dateTimeFactory: const charts.LocalDateTimeFactory(),

animate: true,

defaultInteractions: true,

defaultRenderer: charts.LineRendererConfig(

strokeWidthPx: 3, radiusPx: 5, roundEndCaps: true),

selectionModels: [

charts.SelectionModelConfig(

updatedListener: (charts.SelectionModel model) {

if (model.hasDatumSelection) {

rate = model.selectedSeries.first

.measureFn(model.selectedDatum.first.index)

.toString();

date = formatDateAndTime(

model.selectedDatum.first.datum.date.toString());

ToolTipMgr.setTitle({

'title': '${simpleCurrencyFormat.format(double.parse(rate))} /gm',

'subTitle': '$date'

});

}

},

),

],

behaviors: [

charts.SelectNearest(

eventTrigger: charts.SelectionTrigger.tapAndDrag,

),

charts.LinePointHighlighter(

radiusPaddingPx: 3.0,

showVerticalFollowLine:

charts.LinePointHighlighterFollowLineType.nearest,

symbolRenderer: CustomRectangleSymbolRenderer(),

),

],

domainAxis: charts.DateTimeAxisSpec(

tickProviderSpec: charts.StaticDateTimeTickProviderSpec([

charts.TickSpec(toDateTimeGraph(graphData[0].date),

style: charts.TextStyleSpec(

fontSize: 11,

color: charts.ColorUtil.fromDartColor(Colors.white),

)),

charts.TickSpec(toDateTimeGraph(graphData[15].date),

style: charts.TextStyleSpec(

fontSize: 11,

color: charts.ColorUtil.fromDartColor(Colors.white),

)),

charts.TickSpec(toDateTimeGraph(graphData[30].date),

style: charts.TextStyleSpec(

fontSize: 11,

color: charts.ColorUtil.fromDartColor(Colors.white),

)),

charts.TickSpec(toDateTimeGraph(graphData[45].date),

style: charts.TextStyleSpec(

fontSize: 11,

color: charts.ColorUtil.fromDartColor(Colors.white),

)),

]),

renderSpec: charts.GridlineRendererSpec(

labelAnchor: charts.TickLabelAnchor.inside,

lineStyle: charts.LineStyleSpec(

color: charts.ColorUtil.fromDartColor(

Colors.transparent))),

showAxisLine: true),

animationDuration: Duration(milliseconds: 700),

primaryMeasureAxis: charts.NumericAxisSpec(

tickProviderSpec: charts.BasicNumericTickProviderSpec(

zeroBound: false, desiredTickCount: 4),

showAxisLine: true,

renderSpec: charts.GridlineRendererSpec(

labelAnchor: charts.TickLabelAnchor.centered,

labelStyle: charts.TextStyleSpec(

fontSize: 10,

color: charts.ColorUtil.fromDartColor(Colors.white)),

lineStyle: charts.LineStyleSpec(

color: charts.ColorUtil.fromDartColor(

Colors.transparent))),

),

),

)

You can play around with the animation on and off, animation duration, the color of the plotline, radius of it, and so on.

Now that plotting is done let’s figure out how to show data on the tap of the graph. This is where behaviors and selectionModels come into the picture. Behaviors are where we define the action such as tap or tap and drag.

behaviors: [

charts.SelectNearest(

eventTrigger: charts.SelectionTrigger.tapAndDrag,

),

charts.LinePointHighlighter(

radiusPaddingPx: 3.0,

showVerticalFollowLine:

charts.LinePointHighlighterFollowLineType.nearest,

symbolRenderer: CustomRectangleSymbolRenderer(),

),

],

CustomRectangleSymbolRenderer is used to draw the rectangle and the text which is the selected data from the graph. Let’s take a look at the code of CustomRectangleSymbolRenderer

The position and the dimensions of the shape and the text can be adjusted using the canvas-bound values.

selectionModels gives us the data of the selected values through updatedListener