I am trying to add legend to SfCartesianChart. I am getting "Null check operator used on a null value" error. You can see the code below.
class AllInLineChart extends StatefulWidget {
#override
State<AllInLineChart> createState() => _AllInLineChartState();
final Data chartData;
const AllInLineChart(this.chartData);
}
class _AllInLineChartState extends State<AllInLineChart> {
#override
Widget build(BuildContext context) {
final Data _chart = widget.chartData;
return Container(
margin: margin10,
decoration: boxDecoration,
child: SfCartesianChart(
legend: Legend(isVisible: true),
primaryXAxis: DateTimeAxis(),
primaryYAxis: NumericAxis(),
series: <ChartSeries>[
SplineSeries<dataItem, DateTime>(
name: 'Crypto',
dataSource: _chart.cryptoItems,
xValueMapper: (dataItem data, _) => data.time,
yValueMapper: (dataItem data, _) => data.totalAmountInTime,
markerSettings: MarkerSettings(isVisible: true),
),
SplineSeries<dataItem, DateTime>(
name: 'Stock',
dataSource: _chart.stockItems,
xValueMapper: (dataItem data, _) => data.time,
yValueMapper: (dataItem data, _) => data.totalAmountInTime,
markerSettings: MarkerSettings(isVisible: true),
),
SplineSeries<dataItem, DateTime>(
dataSource: _chart.etfItems,
xValueMapper: (dataItem data, _) => data.time,
yValueMapper: (dataItem data, _) => data.totalAmountInTime,
name: 'ETF',
markerSettings: MarkerSettings(isVisible: true),
),
SplineSeries<dataItem, DateTime>(
dataSource: _chart.currencyItems,
xValueMapper: (dataItem data, _) => data.time,
yValueMapper: (dataItem data, _) => data.totalAmountInTime,
name: 'Currency',
markerSettings: MarkerSettings(isVisible: true),
),
SplineSeries<dataItem, DateTime>(
dataSource: _chart.cashItems,
xValueMapper: (dataItem data, _) => data.time,
yValueMapper: (dataItem data, _) => data.totalAmountInTime,
name: 'Cash',
markerSettings: MarkerSettings(isVisible: true),
),
],
),
);
}
}
You can see error here
If I remove legend: Legend(isVisible: true), from code, it is working without error. But I need legend. Thanks for your help.
You can see working version here
My sample data is:
class dataItem {
final DateTime time;
final double totalAmountInTime;
dataItem(this.time, this.totalAmountInTime);
}
class Data with ChangeNotifier {
final List<dataItem> _cryptoItems = [
dataItem(DateTime.parse("20220820"), 10000),
dataItem(DateTime.parse("20220821"), 5000),
dataItem(DateTime.parse("20220822"), 50000),
dataItem(DateTime.parse("20220823"), 25000),
dataItem(DateTime.parse("20220824"), 100000),
];
List<dataItem> get cryptoItems {
return [..._cryptoItems];
}
final List<dataItem> _stockItems = [
dataItem(DateTime.parse("20220820"), 1000),
dataItem(DateTime.parse("20220821"), 500),
dataItem(DateTime.parse("20220822"), 5000),
dataItem(DateTime.parse("20220823"), 2500),
dataItem(DateTime.parse("20220824"), 10000),
];
List<dataItem> get stockItems {
return [..._stockItems];
}
final List<dataItem> _etfItems = [
dataItem(DateTime.parse("20220820"), 500),
dataItem(DateTime.parse("20220821"), 1000),
dataItem(DateTime.parse("20220822"), 2500),
dataItem(DateTime.parse("20220823"), 5000),
dataItem(DateTime.parse("20220824"), 0),
];
List<dataItem> get etfItems {
return [..._etfItems];
}
final List<dataItem> _currencyItems = [
dataItem(DateTime.parse("20220820"), 5000),
dataItem(DateTime.parse("20220821"), 10000),
dataItem(DateTime.parse("20220822"), 25000),
dataItem(DateTime.parse("20220823"), 50000),
dataItem(DateTime.parse("20220824"), 100000),
];
List<dataItem> get currencyItems {
return [..._currencyItems];
}
final List<dataItem> _cashItems = [
dataItem(DateTime.parse("20220820"), 10000),
dataItem(DateTime.parse("20220821"), 50000),
dataItem(DateTime.parse("20220822"), 25000),
dataItem(DateTime.parse("20220823"), 5000),
dataItem(DateTime.parse("20220824"), 1000),
];
List<dataItem> get cashItems {
return [..._cashItems];
}
}
Related
Why do all the elements in the chart not start from zero, but move to the top?
I want to have my own data for each month (text) and they are separated. They can be grouped together, they can also be single.
Code:
SfCartesianChart(
primaryXAxis: CategoryAxis(),
primaryYAxis: NumericAxis(minimum: 0),
series: <ChartSeries>[
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group A',
dataSource: chartData,
xValueMapper: (TaskChartInfo sales, _) => "Сент",
yValueMapper: (TaskChartInfo sales, _) => 45),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group B',
dataSource: chartData,
xValueMapper: (TaskChartInfo sales, _) => "Сент",
yValueMapper: (TaskChartInfo sales, _) => 32),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group B',
dataSource: chartData,
name: "Авг",
enableTooltip: true,
xValueMapper: (TaskChartInfo sales, _) => "Авг",
yValueMapper: (TaskChartInfo sales, _) => 45),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group A',
dataSource: chartData,
xValueMapper: (TaskChartInfo sales, _) => "Дек",
yValueMapper: (TaskChartInfo sales, _) => 100),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group B',
dataSource: chartData,
xValueMapper: (TaskChartInfo sales, _) => "Окт",
yValueMapper: (TaskChartInfo sales, _) => 21)
])
Thank you in advance for the answer!
While grouping the stacked series, the series x-values should be same for grouping series. For example, stacked series1 and series 2 have groupName as 'Group A' means, both series should have same x values.
You can achieve the requirement by changing the groupName value.
We have prepared and shared a code snippet below for your reference.
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SfCartesianChart(
primaryXAxis: CategoryAxis(),
primaryYAxis: NumericAxis(minimum: 0),
series: <ChartSeries>[
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group A',
dataSource: chartData,
color: Colors.blueAccent,
xValueMapper: (TaskChartInfo sales, _) => "Сент",
yValueMapper: (TaskChartInfo sales, _) => 45),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group A',
dataSource: chartData,
color: Colors.pinkAccent,
xValueMapper: (TaskChartInfo sales, _) => "Сент",
yValueMapper: (TaskChartInfo sales, _) => 32),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group B',
dataSource: chartData,
name: "Авг",
enableTooltip: true,
color: Colors.redAccent,
xValueMapper: (TaskChartInfo sales, _) => "Авг",
yValueMapper: (TaskChartInfo sales, _) => 45),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group C',
dataSource: chartData,
color: Colors.orangeAccent,
xValueMapper: (TaskChartInfo sales, _) => "Дек",
yValueMapper: (TaskChartInfo sales, _) => 100),
StackedColumnSeries<TaskChartInfo, String>(
groupName: 'Group D',
dataSource: chartData,
color: Colors.greenAccent,
xValueMapper: (TaskChartInfo sales, _) => "Окт",
yValueMapper: (TaskChartInfo sales, _) => 21)
],
)),
);
}
}
class TaskChartInfo {
TaskChartInfo(this.name, this.value);
final String name;
final int value;
}
List<TaskChartInfo> chartData = <TaskChartInfo>[
TaskChartInfo("Сент", 45),
TaskChartInfo("Авг", 32),
TaskChartInfo("Дек", 100),
TaskChartInfo("Окт", 100),
];
ScreenShot:
I want to set an image on the index of the Stacked Graph of a flutter on the x-axis.
I created a graph class for this. but I don't know how to add an image on the index of the x-axis like in the picture.
I used (https://pub.dev/packages/syncfusion_flutter_charts/example) this package for graph implementation.
CustomChart.dart
import 'package:climate_karma/utils/values/constant_colors.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import '../model/chartData.dart';
class CustomChart extends StatefulWidget {
const CustomChart({Key? key}) : super(key: key);
#override
State<CustomChart> createState() => _CustomChartState();
}
class _CustomChartState extends State<CustomChart> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
height: 150,
child: Row(
children: [
Container(
width: 48,
color: Colors.white,
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Container(
margin: EdgeInsets.only(top: 25),
child: Icon(Icons.electric_car,size: 30),
),
Container(
margin: EdgeInsets.only(top: 25),
child: Icon(Icons.electric_car,size: 30,),
)
],
),
),
Flexible(
child: SfCartesianChart(
primaryXAxis: CategoryAxis(
isVisible: false,
interval: 1,
),
primaryYAxis: NumericAxis(interval: 1,maximum: 6),
backgroundColor: Colors.white,
series: <ChartSeries>[
StackedBarSeries<ChartData, String>(
dataSource: ChartData.chartDataList,
color: ConstantColors.greenVoilrtColor,
xValueMapper: (ChartData data, _) => data.name,
yValueMapper: (ChartData data, _) => data.index
),
StackedBarSeries<ChartData, String>(
dataSource: ChartData.chartDataList,
color: ConstantColors.orengeColor,
xValueMapper: (ChartData data, _) => data.name,
yValueMapper: (ChartData data, _) =>data.index,
),
StackedBarSeries<ChartData, String>(
dataSource: ChartData.chartDataList,
color: ConstantColors.yellowColor,
xValueMapper: (ChartData data, _) => data.name,
yValueMapper: (ChartData data, _) => data.index
),
StackedBarSeries<ChartData, String>(
dataSource: ChartData.chartDataList,
color: ConstantColors.zestColor,
xValueMapper: (ChartData data, _) => data.name,
yValueMapper: (ChartData data, _) => data.index
),
StackedBarSeries<ChartData, String>(
dataSource: ChartData.chartDataList,
color: ConstantColors.bianchiGreenColor,
xValueMapper: (ChartData data, _) => data.name,
yValueMapper: (ChartData data, _) => data.index
)
]
),
),
],
)
)
);
}
}
CharData.dart
import 'dart:ui';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter/material.dart';
class ChartData{
String name;
String image;
Widget material;
num index;
ChartData({required this.index,required this.name, required this.image,required this.material});
static List<ChartData> chartDataList = [
ChartData(index: 0,name: "elec", image: "assets/images/icon_power.svg",material: SvgPicture.asset("assets/images/icon_power.svg")) ,
ChartData(index: 1.3,name: "elec", image: "assets/images/icon_transport.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
ChartData(index: 1.3,name: "elec", image: "assets/images/icon_power.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
ChartData(index: 1.5,name: "elec", image: "assets/images/icon_power.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
ChartData(index: 1.6,name: "elec", image: "assets/images/icon_power.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
ChartData(index: 4,name: "fuel", image: "assets/images/icon_power.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
ChartData(index: 5,name: "fuel", image: "assets/images/icon_transport.svg",material: SvgPicture.asset("assets/images/icon_power.svg")),
];
}
I am trying to implement my API data in a chart using fl_chart dependencies in flutter. But I just cannot figure out how to implement it.
Here is how I implement my data:
#override
Widget build(BuildContext context) {
return ListView.builder(
padding: EdgeInsets.zero,
shrinkWrap: true,
scrollDirection: Axis.vertical,
physics: NeverScrollableScrollPhysics(),
itemCount: 1,
itemBuilder: (context, index){
// ignore: unused_local_variable
int number = index + 1;
return Container(
width: MediaQuery.of(context).size.width * 0.50,
child: LineChart(
LineChartData(
gridData: FlGridData(
show: true,
drawVerticalLine: true,
getDrawingHorizontalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
getDrawingVerticalLine: (value) {
return FlLine(
color: const Color(0xff37434d),
strokeWidth: 1,
);
},
),
titlesData: FlTitlesData(
show: true,
bottomTitles: SideTitles(
showTitles: true,
reservedSize: 22,
getTextStyles: (value) =>
const TextStyle(color: Color(0xff68737d), fontWeight: FontWeight.bold, fontSize: 16),
getTitles: (value) {
switch (value.toInt()) {
case 2:
return 'MAR';
case 5:
return 'JUN';
case 8:
return 'SEP';
}
return '';
},
margin: 8,
),
leftTitles: SideTitles(
showTitles: true,
getTextStyles: (value) => const TextStyle(
color: Color(0xff67727d),
fontWeight: FontWeight.bold,
fontSize: 15,
),
getTitles: (value) {
switch (value.toInt()) {
case 1:
return '10k';
case 3:
return '30k';
case 5:
return '50k';
}
return '';
},
reservedSize: 28,
margin: 12,
),
),
borderData:
FlBorderData(show: true, border: Border.all(color: const Color(0xff37434d), width: 1)),
minX: 0,
maxX: 11,
minY: 0,
maxY: 6,
lineBarsData: [
LineChartBarData(
spots: [
FlSpot(0 , pings[number.toString()][index].volume),
FlSpot(2.6, 2),
FlSpot(4.9, 5),
FlSpot(6.8, 3.1),
FlSpot(8, 4),
FlSpot(9.5, 3),
FlSpot(11, 4),
],
isCurved: true,
colors: gradientColors,
barWidth: 5,
isStrokeCapRound: true,
dotData: FlDotData(
show: true,
),
belowBarData: BarAreaData(
show: true,
colors: gradientColors.map((color) => color.withOpacity(0.3)).toList(),
),
),
],
)
And here is how i call my data:
Map<String, List<TankPing>> pings;
initState() {
Services.fetchPing().then((tankPings) => {
setState((){
pings = tankPings;
})
});
super.initState();
}
My API call is in another file. I call the API like below:
static Future<Map<String, List<TankPing>>> fetchPing() async {
String url3 = 'https://api.orbital.katsana.com/devices/graph-data';
Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
final SharedPreferences prefs = await _prefs;
final token = prefs.getString('access_token');
final response3 = await http.get(url3, headers: {
'Authorization': 'Bearer $token'
});
if(response3.statusCode == 200) {
final tankPings = tankPingFromJson(response3.body);
return tankPings;
}else if(response3.statusCode == 400) {
print('Connection to server is bad');
}else if(response3.statusCode == 500){
print('No authorization');
}
}
I am trying to implement it inside of FlSPot() function. But then U receive this error:
The method '[]' was called on null.
Receiver: null
Tried calling: []("1")
Here is my model:
import 'dart:convert';
Map<String, List<TankPing>> tankPingFromJson(dynamic str) => Map.from(json.decode(str)).map((k, v) => MapEntry<String, List<TankPing>>(k, List<TankPing>.from(v.map((x) => TankPing.fromJson(x)))));
String tankPingToJson(Map<String, List<TankPing>> data) => json.encode(Map.from(data).map((k, v) => MapEntry<String, dynamic>(k, List<dynamic>.from(v.map((x) => x.toJson())))));
class TankPing {
TankPing({
this.trackedAt,
this.fuel,
this.level,
this.volume,
});
DateTime trackedAt;
double fuel;
double level;
double volume;
factory TankPing.fromJson(Map<String, dynamic> json) => TankPing(
trackedAt: DateTime.parse(json["tracked_at"]),
fuel: json["fuel"].toDouble(),
level: json["level"].toDouble(),
volume: json["volume"].toDouble(),
);
Map<String, dynamic> toJson() => {
"tracked_at": trackedAt.toString(),
"fuel": fuel,
"level": level,
"volume": volume,
};
}
Here is how the API look:
{
"1": [
{
"tracked_at": "2020-11-20T19:41:21.000000Z",
"fuel": 87.03,
"level": 3.0460554,
"volume": 50665.14
},
{
"tracked_at": "2020-11-22T00:19:41.000000Z",
"fuel": 85.75,
"level": 3.0012249,
"volume": 50051.86
},
{
"tracked_at": "2020-11-22T00:32:00.000000Z",
"fuel": 84.17,
"level": 2.9460489,
"volume": 49265.04
},
]
My API is very long and it looks like that. Any help would be appreciated.
I just post the code example in here. If you have any question, you can ask me and I will try to answer the question I can because this code is like almost 2 or 3 years old now and I did not work on this project anymore. Hope the code below helps you!
import 'package:charts_flutter/flutter.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:intl/intl.dart';
import 'custom_symbol_renderer.dart';
import 'package:orbital_app/Model/tank_ping.dart';
import 'package:orbital_app/Provider/api_provider.dart';
class TankChart extends StatefulWidget {
//This is my API class object to extract the data
TankChart({Key key}) : super(key: key);
#override
_TankChartState createState() => _TankChartState();
}
class _TankChartState extends State<TankChart> {
var ping;
var tankInfo;
// Since I am using a Provider in this code, I call the API here
getPingProvider(){
setState((){
ping = Provider.of<TankPingProvider>(context, listen: false);
ping.getTankPing(context);
});
}
getInfoProvider(){
setState((){
tankInfo = Provider.of<TankInfoProvider>(context, listen: false);
tankInfo.getTankInfo(context);
});
}
#override
initState() {
super.initState();
getPingProvider();
getInfoProvider();
}
#override
Widget build(BuildContext context) {
// Here I format the time to normal human time
final numericFormatter = charts.BasicNumericTickFormatterSpec.fromNumberFormat(
NumberFormat.compact()
);
final ping = Provider.of<TankPingProvider>(context);
return ListView.builder(
padding: EdgeInsets.zero,
// Here I want everything to be shrink and expand when the user needs it
shrinkWrap: true,
// Here is where I set whether the graph can be expand by user vertical
// scroll
physics: NeverScrollableScrollPhysics(),
//The data from the API is here
itemCount: ping.tankPing.length,
itemBuilder: (context, index){
if(ping.tankPing.length == null){
return CircularProgressIndicator();
} else if(ping.tankPing == null){
return CircularProgressIndicator();
} else{
int no = index + 1;
final size = MediaQuery.of(context).size;
// Here is the API dot or data dot on the graph
List<charts.Series<TankPing, DateTime>> series = [
charts.Series(
id: '${tankInfo.tankInfos.data[index].name}',
data: ping.tankPing[no.toString()],
colorFn: (_, __) => MaterialPalette.blue.shadeDefault,
domainFn: (TankPing ping, _) => ping.trackedAt,
measureFn: (TankPing ping, _) => ping.volume
),
];
return Container(
height: 250,
child: Card(
child: Column(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.only(
left: 5
),
child: charts.TimeSeriesChart(
series,
animate: false,
domainAxis: charts.DateTimeAxisSpec(
tickFormatterSpec: charts.AutoDateTimeTickFormatterSpec(
day: charts.TimeFormatterSpec(
format: 'dd',
transitionFormat: 'dd MMM',
),
),
),
primaryMeasureAxis: charts.NumericAxisSpec(
tickFormatterSpec: numericFormatter,
renderSpec: charts.GridlineRendererSpec(
// Tick and Label styling here.
labelStyle: charts.TextStyleSpec(
fontSize: 10, // size in Pts.
color: charts.MaterialPalette.black
),
)
),
defaultRenderer: charts.LineRendererConfig(
includeArea: true,
includeLine: true,
includePoints: true,
strokeWidthPx: 0.5,
radiusPx: 1.5
),
dateTimeFactory: const charts.LocalDateTimeFactory(),
behaviors: [
charts.SlidingViewport(),
charts.PanAndZoomBehavior(),
charts.SeriesLegend(
position: charts.BehaviorPosition.top,
horizontalFirst: false,
cellPadding: EdgeInsets.only(
left: MediaQuery.of(context).size.width * 0.27,
top: 15
),
),
charts.SelectNearest(
eventTrigger: charts.SelectionTrigger.tap
),
charts.LinePointHighlighter(
symbolRenderer: CustomCircleSymbolRenderer(size: size),
),
],
selectionModels: [
charts.SelectionModelConfig(
type: charts.SelectionModelType.info,
changedListener: (charts.SelectionModel model) {
if(model.hasDatumSelection) {
final tankVolumeValue = model.selectedSeries[0].measureFn(model.selectedDatum[0].index).round();
final dateValue = model.selectedSeries[0].domainFn(model.selectedDatum[0].index);
CustomCircleSymbolRenderer.value = '$dateValue \n $tankVolumeValue L';
}
})
]),
),
),
],
),
),
);
}
});
}
}
The answer is use the min and max value to determine how long the data will be. And then just use the flSpot to enter your data.
Im trying to create a chart that updates the data by checking every 4 seconds. It checks if the last element of the list is the same as the single element in another list. If not, it will remove the first element and add the newest element in. However this is not updating my graph and it only stays as the initial data. Help please ?
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:syncfusion_flutter_charts/charts.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'globalvar.dart';
import 'home_screen.dart';
import 'chartjsonparse.dart';
class RealHumidityChart extends StatefulWidget {
#override
_RealHumidityChartState createState() => _RealHumidityChartState();
}
class _RealHumidityChartState extends State<RealHumidityChart> {
List<SensorData> chartData = []; // list for storing the last parsed Json data
List<SensorData> singleData = [];
Timer _clearTimer;
Future<String> getChartJsonFromDatabase() async {
// Sending get(url) request using the http client to retrieve the response.
var fullResponse = await http.get(fullUrl);
return fullResponse.body;
}
Future loadSensorData() async {
String jsonString = await getChartJsonFromDatabase(); // Deserialization Step #1
final jsonResponse = json.decode(jsonString); // // Deserialization Step #2
setState(() {
// Mapping the retrieved json response string and adding the sensor data to the chart data list.
for (Map i in jsonResponse) {
chartData.add(
SensorData.fromJson(i) // Deserialization step #3
);
}
});
}
Future loadSingleData() async {
var singleResponse = await http.get(singleUrl);
if (singleResponse.statusCode == 200) {
final singleJsonResponse = json.decode(singleResponse.body);
for (Map i in singleJsonResponse) {
singleData.add(
SensorData.fromJson(i)
);
print("Sucessfully connect singlecode");
print(chartData);
}
}
}
#override
void initState() {
loadSensorData();
_clearTimer = Timer.periodic(Duration(seconds: 4), (Timer t) {
singleData.clear();
loadSingleData();
if (chartData.last != singleData.last){
chartData.removeAt(0);
chartData.add(singleData.last);
setState(() {});
}
});
super.initState();
}
#override
void dispose() {
_clearTimer.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xff264653),
),
body: SfCartesianChart(
margin: EdgeInsets.all(15),
primaryXAxis: CategoryAxis(
title: AxisTitle(
text: "Date",
)
),
primaryYAxis: NumericAxis(
// '%' will be append to all Y-axis labels
labelFormat: '{value} %'
),
//Chart Title
title: (ChartTitle(text: 'Humidity')),
//Enable legend
legend: Legend(isVisible: false),
//Enable tooltip
tooltipBehavior: TooltipBehavior(enable: true),
series: <ChartSeries<SensorData, String>>[
LineSeries<SensorData, String>(
name: 'Humidity Chart',
dataSource: chartData,
xValueMapper: (SensorData data, _) => data.date,
yValueMapper: (SensorData data, _) => data.sen1,
//Enable Label Settings
dataLabelSettings: DataLabelSettings(isVisible: true),
markerSettings: MarkerSettings(isVisible: true),
),
]
),
);
}
}
class SensorData {
SensorData(this.date, this.sen1);
String date;
dynamic sen1;
factory SensorData.fromJson(Map<String, dynamic> parsedJson) {
return SensorData(
parsedJson['Date'].toString(),
parsedJson['Sen1'] as dynamic,
);
}
}
Add SfCartesianChart inSide Future Builder and Update future of FutureBuilder when you want to update like below code.
FutureBuilder(
future: futureDailyCount,
builder: (context, snapshot) {
if (snapshot.hasData) {
return Column(
children: <Widget>[
SfCartesianChart(
plotAreaBorderWidth: 0,
title: ChartTitle(text: 'Daily Progress'),
legend: Legend(
isVisible: isCardView ? false : true,
overflowMode: LegendItemOverflowMode.wrap),
primaryXAxis: CategoryAxis(
// Axis will be rendered based on the index values
interval: 1,
labelRotation: 90,
arrangeByIndex: true
),
primaryYAxis: NumericAxis(
edgeLabelPlacement: EdgeLabelPlacement.shift,
// labelFormat: '{value}k',
axisLine: const AxisLine(width: 0),
majorTickLines: const MajorTickLines(color: Colors.transparent)
),
tooltipBehavior: TooltipBehavior(enable: true),
series: <ChartSeries<DailyCount, String>>[
LineSeries<DailyCount, String>(
animationDuration: 2500,
width: 2,
name: '',
markerSettings: const MarkerSettings(isVisible: true),
dataSource: chartDataDailyCount!,
xValueMapper: (DailyCount sensors, _) => sensors.xaxis,
yValueMapper: (DailyCount sensors, _) => sensors.collectCount,
),
]
),
SizedBox(height:50),
// Column(children: [
// SfCartesianChart(
// plotAreaBorderWidth: 0,
// title: ChartTitle(text: 'Surveyor Progress'),
// legend: Legend(
// isVisible: isCardView ? false : true,
// overflowMode: LegendItemOverflowMode.wrap),
// primaryXAxis: CategoryAxis(
// // Axis will be rendered based on the index values
// interval: 1,
// labelRotation: 90,
// arrangeByIndex: true
// ),
// primaryYAxis: NumericAxis(
// edgeLabelPlacement: EdgeLabelPlacement.shift,
// // labelFormat: '{value}k',
// // minimum: 0,
// // maximum: 12,
// axisLine: const AxisLine(width: 0),
// majorTickLines: const MajorTickLines(color: Colors.transparent)
// ),
// tooltipBehavior: TooltipBehavior(enable: true),
// series: <ChartSeries<SurveyourCount, String>>[
// LineSeries<SurveyourCount, String>(
// animationDuration: 2500,
// width: 2,
// name: '',
// color: Colors.red,
// markerSettings: const MarkerSettings(isVisible: true),
// dataSource: chartDataSurveyourCount,
// xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime1,
// yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount1,
// ),
// LineSeries<SurveyourCount, String>(
// animationDuration: 2500,
// width: 2,
// name: '',
// color: Colors.red,
// markerSettings: const MarkerSettings(isVisible: true),
// dataSource: chartDataSurveyourCount,
// xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime1,
// yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount1,
// ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.green,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime2,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount2,
// // ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.blue,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime3,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount3,
// // ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.yellow,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime4,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount4,
// // ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.black,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime5,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount5,
// // ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.orange,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime6,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount6,
// // ),
// // LineSeries<SurveyourCount, String>(
// // animationDuration: 2500,
// // width: 2,
// // name: '',
// // color: Colors.pink,
// // markerSettings: const MarkerSettings(isVisible: true),
// // dataSource: chartDataSurveyourCount,
// // xValueMapper: (SurveyourCount sales, _) => sales.dbDateTime7,
// // yValueMapper: (SurveyourCount sales, _) => sales.totalSurveyorCount7,
// // ),
//
//
// ]
//
// ),
// ]
// ),
//--------------------------------------------
// Container(
// width: 30,
// height: 30 ,
// color: Colors.red,
// ),
// ],)
// FutureBuilder(
// future: futureMonthlyCount,
// builder: (context, snapshot) {
// if (snapshot.hasData) {
// return SfCartesianChart(
// plotAreaBorderWidth: 0,
// title: ChartTitle(text: 'Monthly Progress'),
// legend: Legend(
// isVisible: isCardView ? false : true,
// overflowMode: LegendItemOverflowMode.wrap),
// primaryXAxis: CategoryAxis(
// // Axis will be rendered based on the index values
// interval: 1,
// labelRotation: 90,
// arrangeByIndex: true
// ),
// primaryYAxis: NumericAxis(
// edgeLabelPlacement: EdgeLabelPlacement.shift,
// // labelFormat: '{value}k',
// // minimum: 0,
// // maximum: 12,
// axisLine: const AxisLine(width: 0),
// majorTickLines: const MajorTickLines(color: Colors.transparent)
// ),
// tooltipBehavior: TooltipBehavior(enable: true),
// series: <ChartSeries<MonthlyCount, String>>[
// LineSeries<MonthlyCount, String>(
// animationDuration: 2500,
// width: 2,
// name: '',
// markerSettings: const MarkerSettings(isVisible: true),
//
//
//
//
// dataSource: chartDataMonthlyCount!,
// xValueMapper: (MonthlyCount sales, _) => sales.xaxis,
// yValueMapper: (MonthlyCount sales, _) => sales.collectCount,
// ),
//
// ]
//
// );
// }
// else {
// return CircularProgressIndicator();
// }
// }
// ),
],
);
}
else if (snapshot.hasError) {
// return Text('${snapshot.error}');
return Column(children: [
Padding(
padding: EdgeInsets.all(60),
child:Text('Internet Connection Problem',style:TextStyle(fontSize: 18))),
FlatButton(
child: Text('Refreash', style: TextStyle(fontSize: 20.0),),
onPressed: () {
check().then((intenet) async {
if (intenet != null && intenet) {
setState(() {
futureDailyCount = fetchDailyCount('all','all','all');
});
print('internet Conneciton present');
}else{
print('internet Conneciton Not present');
showAlertDialogInternetNotPresent(context);
}
});
},
),
]);
}
// By default, show a loading spinner.
return Container(
alignment: Alignment.topCenter,
margin: EdgeInsets.only(top: 40),
child: CircularProgressIndicator()
);
}
),
i'm facing issues in line charts. i'm fetching x and y data from sq lite database. and it should set
in line chart.when activity started chart showing blank. but only click on chart value is setting in
chart.
i'm using charts_flutter dart package for implementation.
where i did the mistake. any solutions.
Future graph_initialize() {
Future<List<Map>> noteListFuture1 = dbHelper.get_lactation_curve("${widget.value.tag}");//fetching data from databse
noteListFuture1.then((noteList) {
for(int i=0;i<noteList.length;i++){
print(noteList[i]["Days"].toString()+","+noteList[i]["Milk_Yield"].toString());
milking_data.add( new Sales(noteList[i]["Days"], noteList[i]["Milk_Yield"]));
}
_serieslineData.add(charts.Series(
colorFn: (__, _) => charts.ColorUtil.fromDartColor(Colors.red),
id: 'lac',
data: milking_data,// here data is setting
domainFn: (Sales sales, _) => sales.yearval,
measureFn: (Sales sales, _) => sales.salesval));
setState(() {
});
});}
#override
void initState() {
super.initState();
_serieslineData = List<charts.Series<Sales, int>>();
graph_initialize();//function call
}
Widget show_chart(){
return Padding(
padding: EdgeInsets.all(8),
child: Container(
height: 300,
child: Column(
children: <Widget>[
Text('Lactation Curve',
style: TextStyle(fontSize: 16, fontFamily: 'Montserrat',fontWeight: FontWeight.bold)),
Expanded(
child: charts.LineChart(_serieslineData,
animate: false,
domainAxis: charts.NumericAxisSpec(
tickProviderSpec:
new charts.BasicNumericTickProviderSpec(
desiredTickCount: 11,
),
viewport: charts.NumericExtents(
0,
300,
)),
animationDuration: Duration(seconds: 3),
behaviors: [
charts.ChartTitle('Milk Yield',
behaviorPosition: charts.BehaviorPosition.start),
charts.ChartTitle('Days in Milk',
behaviorPosition: charts.BehaviorPosition.bottom),
charts.ChartTitle(
'',
),
charts.ChartTitle(' ')
])),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[label(Colors.red,'Lac'),
label(Colors.lightBlueAccent,'Milk(kg)'),
label(Colors.amber,'A.I'),
label(Colors.green,'Pregnant'),
label(Colors.blueGrey,'Vaccination'),
label(Colors.black,'Treatment'),
],
),
)
],
),
),
);
}
You need a bool loading or isLoading to control because chart data is not ready yet
and when loading == true return CircularProgressIndicator() or Container()
bool loading = false;
Future graph_initialize() {
loading = true;
Future<List<Map>> noteListFuture1 = dbHelper.get_lactation_curve("${widget.value.tag}");//fetching data from databse
noteListFuture1.then((noteList) {
for(int i=0;i<noteList.length;i++){
print(noteList[i]["Days"].toString()+","+noteList[i]["Milk_Yield"].toString());
milking_data.add( new Sales(noteList[i]["Days"], noteList[i]["Milk_Yield"]));
}
_serieslineData.add(charts.Series(
colorFn: (__, _) => charts.ColorUtil.fromDartColor(Colors.red),
id: 'lac',
data: milking_data,// here data is setting
domainFn: (Sales sales, _) => sales.yearval,
measureFn: (Sales sales, _) => sales.salesval));
setState(() {
loading = false;
});
});}
Expanded(
child: loading? CircularProgressIndicator() : charts.LineChart(_serieslineData,
animate: false,
domainAxis: charts.NumericAxisSpec(
tickProviderSpec: