I am trying to display a list in flutter. The list has 2 parts, one is the parent name and under that, I have the subcategories. I am fetching the data using an API and trying to create checkboxes using the fetched data. I am unable to understand how to display the lists properly. As posted in the image, the main header is being displayed equal to the number of categories it holds. I want to display a single header and the subcategories under it. Kindly Help.
Function for List Builder
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Column(
children: [
ExpansionTile(
title: Text(snapshot.data[index].p_cat_name),
children: [
ListTile(
title: Text(snapshot.data[index].c_cat_name),
leading: Checkbox(
value: CategoriesDsiplay.userStatus[index] =
!CategoriesDsiplay.userStatus[index],
onChanged: (bool? val) {
setState(() {
CategoriesDsiplay.userStatus[index] =
!CategoriesDsiplay.userStatus[index];
});
},
),
),
],
),
],
);
},
);
Function for adding data to the list
Future<List<CategoryFiltersList>> getCategoryList() async {
var url = Uri.parse(
urlhere );
final headers = {'Content-Type': 'application/x-www-form-urlencoded'};
Map<String, dynamic> body = {
'st_search': '',
};
final encoding = Encoding.getByName('utf-8');
Response response = await post(
url,
headers: headers,
body: body,
encoding: encoding,
);
var schemeBody = response.body;
var jsonData = json.decode(schemeBody);
List<CategoryFiltersList> categoryFiltersLists = [];
for (var sch in jsonData) {
// String credentials = sch['isin'];
// Codec<String, String> stringToBase64 = utf8.fuse(base64);
// Body.encoded =
// stringToBase64.encode(credentials); // dXNlcm5hbWU6cGFzc3dvcmQ=
CategoryFiltersList categoryFiltersList = CategoryFiltersList(
sch['mf_cat_id'],
sch['p_cat_name'],
sch['c_cat_name'],
);
if (sch['mf_cat_id'] != null) {}
categoryFiltersLists.add(categoryFiltersList);
CategoriesDsiplay.userStatus.add(false);
}
return categoryFiltersLists;
}
Json Data:
flutter: [{mf_cat_id: 6, p_cat_name: EQUITY, c_cat_name: Value_Fund}, {mf_cat_id: 7, p_cat_name: EQUITY, c_cat_name: Large_Cap}, {mf_cat_id: 8, p_cat_name: EQUITY, c_cat_name: Large_&_Midcap}, {mf_cat_id: 9, p_cat_name: EQUITY, c_cat_name: Multicap}, {mf_cat_id: 10, p_cat_name: EQUITY, c_cat_name: Midcap}, {mf_cat_id: 11, p_cat_name: EQUITY, c_cat_name: Small_Cap}, {mf_cat_id: 13, p_cat_name: EQUITY, c_cat_name: Focussed_Fund}, {mf_cat_id: 14, p_cat_name: EQUITY, c_cat_name: Dividend_Yield_Fund}, {mf_cat_id: 15, p_cat_name: HYBRID, c_cat_name: Arbitrage_Fund}, {mf_cat_id: 16, p_cat_name: HYBRID, c_cat_name: Conservative_Hybrid_Fund}, {mf_cat_id: 17, p_cat_name: HYBRID, c_cat_name: Equity_Savings_Fund}, {mf_cat_id: 18, p_cat_name: HYBRID, c_cat_name: Dynamic_Asset_Allocation_Fund}, {mf_cat_id: 19, p_cat_name: HYBRID, c_cat_name: Balanced_Advantage_Fund}, {mf_cat_id: 20, p_cat_name: HYBRID, c_cat_name: Aggressive_Hybrid_Fund}, {mf_cat_id: 21, p_cat_name: HYBRID, c_cat_name: Multi_Assest_Allocatio<…>
Your ListView.builder builds this for every one of your responses:
Column(
children: [
ExpansionTile(
title: Text(snapshot.data[index].p_cat_name),
children: [
ListTile(
title: Text(snapshot.data[index].c_cat_name),
leading: Checkbox(
value: CategoriesDsiplay.userStatus[index] =
!CategoriesDsiplay.userStatus[index],
onChanged: (bool? val) {
setState(() {
CategoriesDsiplay.userStatus[index] =
!CategoriesDsiplay.userStatus[index];
});
},
),
),
],
),
],
);
The problem with this is that your app builds a new ExpansionTile for every element in your response list.
To fix this you have to find out which and how many 'p_cat_name's your response has and build an ExpansionTile for every p_cat_name. As a child it should have another ListView.builder that builds a ListTile for every element from response array that has the same p_cat_name as the parent (you can do this with if statement checks).
Related
this is my first provider class. I'm trying to retrieve the name of my item from my list
before getting this error I got another error that said '_internallinkedhashmap<string, dynamic>' I search that online and add .cast<String, dynamic>().
now I'm getting this one. is this something to do with my list length
import 'package:ecnomic/provider/provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:provider/provider.dart';
import '../service/colors.dart';
class ItemProperties extends StatefulWidget {
const ItemProperties({super.key});
#override
State<ItemProperties> createState() => _ItemPropertiesState();
}
class _ItemPropertiesState extends State<ItemProperties> {
#override
Widget build(BuildContext context) {
List items = [];
final itemprovider =
Provider.of<onlineShopingProvider>(context, listen: false);
items = itemprovider.getOnlineItem;
return Container(
color: Colors.blue,
height: 500,
width: double.infinity,
child: GridView.builder(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
// mainAxisSpacing: 10,
// childAspectRatio: 3 / 2,
),
itemCount: 20,
itemBuilder: ((context, index) {
return
// Card(
// color: Colors.amber,
// child:
Column(
children: [
Image.network(
'https://hips.hearstapps.com/hmg-prod/images/2020-bmw-750i-xdrive-252-1566180109.jpg?crop=1.00xw:0.927xh;0,0.0366xh&resize=2048:*'),
Text('$index'),
Text(
'${itemprovider.getOnlineItem[index].item_name.cast<String, dynamic>()}'),
],
);
//);
})));
}
}
and this is my provider class
import 'package:flutter/material.dart';
class onlineShopingProvider with ChangeNotifier {
final dynamic _onlineitem = [
{
"item_id": 2,
"item_name": "Jeep Wrangler Sahara",
"item_price": "80000",
"item_image":
"https://www.motortrend.com/uploads/sites/11/2020/01/2020-Jeep-Wrangler-Unlimited-Sahara-4x4-25958.jpg?fit=around%7C875:492",
"category_id": 22,
"category_name": "Jeep",
"item_color": "#FF0000"
},
{
"item_id": 2,
"item_name": "Jeep Wrangler Sahara",
"item_price": "80000",
"item_image":
"https://www.motortrend.com/uploads/sites/11/2020/01/2020-Jeep-Wrangler-Unlimited-Sahara-4x4-25958.jpg?fit=around%7C875:492",
"category_id": 22,
"category_name": "Jeep",
"item_color": "#FF0000"
},
{
"item_id": 18,
"item_name": "Jeep Grand Cherokee Summit",
"item_price": "80000",
"item_image":
"https://hips.hearstapps.com/hmg-prod/images/2023-jeep-grand-cherokee-summit-4x4-101-1667328305.jpeg?crop=0.617xw:0.520xh;0.353xw,0.451xh&resize=2048:*",
"category_id": 22,
"category_name": "Jeep",
"item_color": "#FF0000"
},
{
"item_id": 3,
"item_name": "BMW X5",
"item_price": "100000",
"item_image":
"https://www.motortrend.com/uploads/2022/11/2023-BMW-X5-xDrive40i-front-three-quarter-view-11.jpg?fit=around%7C875:492.1875",
"category_id": 23,
"category_name": "BMW",
"item_color": "#000000"
},
{
"item_id": 4,
"item_name": "BMW 7 Series",
"item_price": "100000",
"item_image":
"https://hips.hearstapps.com/hmg-prod/images/2020-bmw-750i-xdrive-252-1566180109.jpg?crop=1.00xw:0.927xh;0,0.0366xh&resize=2048:*",
"category_id": 23,
"category_name": "BMW",
"item_color": "#000000"
},
{
"item_id": 4,
"item_name": "BMW 8 Series",
"item_price": "107000",
"item_image":
"https://www.caranddriver.com/photos/g27011971/2020-bmw-7-series-drive-gallery/",
"category_id": 23,
"category_name": "BMW",
"item_color": "#000000"
}
];
final dynamic shopingCatagory = [
{
"category_id": 22,
"category_name": "Jeep",
"category_image": "https://pngimg.com/uploads/jeep/jeep_PNG95.png"
},
{
"category_id": 24,
"category_name": "Toyota",
"category_image":
"https://www.freepnglogos.com/uploads/toyota-logo-png/toyota-logos-brands-logotypes-0.png"
},
{
"category_id": 23,
"category_name": "BMW",
"category_image":
"https://pngimg.com/uploads/bmw_logo/bmw_logo_PNG19714.png"
}
];
get getOnlineItem => _onlineitem;
get getShopingCatagory => shopingCatagory;
}
Your itemCount should be the size of the list, try changing to
itemCount: itemprovider.getOnlineItem.length,
And also change your text to this
Text(itemprovider.getOnlineItem[index]['item_name']),
You are setting hard-code value itemCount: 20, but list doesn't contains this much data. You can do
itemCount: items.lenght,
itemCount: items.length,
use size of your list.when you give item count greater than size of your list it will throw an error
also you dont have to access list in provider because you already assigned it to block variable items
items[index].item_name
How can i make a grouped json data to a list in flutter? I have grouped jsondata.
final data = body.data['items']; // gets json data here
final uniqueSetOfChapters =groupBy(data, (dynamic obj) => obj['chapter']); // grouping it here
uniqueSetOfChapters.forEach((key, value) {
print('$key : : $value');
});
As a result i'm getting a grouped data as follows
Measurement : : [
{sequenceno: 193, _id: 5dc1, chapter: Measurement, title: Measuring Length, package_description: Let us learn about ‘Measurement using Length'., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 193, _id: 5d99, chapter: Measurement, title: Measuring Weight, package_description: Let us learn about ‘Measuring Weight’., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 1933, _id: 5d99, chapter: Measurement, title: Measuring Capacity, package_description: This module introduces how to measure the capacity of a container., age_level: [99, 6], pkg_sequence: 251},
{sequenceno: 193, _id: 5ef4, chapter: Measurement, title: Revision - Measuring Length, package_description: In this module, we will revise about measurement using length., age_level: [99, 6], pkg_sequence: 2514],
Data Handling : : [
{sequenceno: 193, _id: 5e23, chapter: Data Handling, title: Bar chart, package_description: This module helps to understand how to represent data., age_level: [99, 6], pkg_sequence: 2511},
{sequenceno: 193, _id: 5f15, chapter: Data Handling, title: Revision - Bar chart, package_description: Let us revise some activities on presenting data in the form of graphs., age_level: [99, 6], pkg_sequence: 251}
]
How can i make this grouped data to a list? I have created a model for this as follows
class Titles{
String? sequenceno;
String? id;
String? chapter;
String? title;
String? packageDescription;
String? ageLevel;
String? pkgSequence;
String? packagescors;
Titles({
this.sequenceno,
this.id,
this.chapter,
this.title,
this.packageDescription,
this.ageLevel,
this.pkgSequence,
this.packagescors,
});
factory Titles.fromMap(Map<String, dynamic> map) {
return Titles(
sequenceno: map['sequenceno'],
id: map["_id"],
chapter: map['chapter'],
title: map['title'],
packageDescription: map['package_description'],
ageLevel: map['age_level'],
pkgSequence: map['pkg_sequence'],
// packagescors: map['packagescors'],
);
}
Map<String, dynamic> toMap(){
var map = <String,dynamic>{
"sequenceno": sequenceno,
"_id": id,
"chapter": chapter,
"title": title,
"package_description": packageDescription,
"age_level": ageLevel,
"pkg_sequence": pkgSequence,
"packagescors": packagescors,
};
return map;
}}
How can I add this grouped data to a list??
You can try with grouped_list package: https://pub.dev/packages/grouped_list
Output sample:
Code snippet:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: Appbar(title: "Titles",),
body: Container(
child: GroupedListView<dynamic, String>(
elements: measurements,
groupBy: (element) => element.chapter,
groupComparator: (value1, value2) => value2.compareTo(value1),
order: GroupedListOrder.ASC,
useStickyGroupSeparators: true,
groupSeparatorBuilder: (String value) => Padding(
padding: const EdgeInsets.only(left: 8.0),
child: Text(
value,
textAlign: TextAlign.start,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Theme.of(context).primaryColor),
),
),
itemBuilder: (c, element) {
return Column(
children: <Widget>[
ListTile(
title: Text(
element.title,
style: TextStyle(fontSize: 14, fontWeight: FontWeight.bold),
),
subtitle: Text(
element.packageDescription,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 12, ),
),
onTap: () => {},
),
],
);
},
),
),
);
}
I assume you want to convert a list of map :
measurement = [{'sequenceno': '193', '_id': '5d99',... }, {'sequenceno': '1933', '_id': '5d99', ..}, {...}, {...}]
into a list of Titles.
What you can do is :
var titleList = [for (var map in measurement) Titles.fromMap(map) ];
For information, you don't need to use a Factory constructor. The following constructor should work as well :
Titles.fromMap(Map<String, dynamic> map) :
sequenceno = map['sequenceno'],
id = map["_id"],
chapter = map['chapter'],
title = map['title'],
packageDescription = map['package_description'],
ageLevel = map['age_level'],
pkgSequence = map['pkg_sequence'];
I have a list item:
var listCodeSensations = [4, 3, 2, 3, 2, 4, 3, 4, 2, 5, 2, 2, 3, 4, 5, 6, 0, 4, 8, 3, 2, 1];
And I have in a costant file this model:
static final List<SensationItem> sensationList = [
SensationItem(
code: 0,
title: 'Formicolio / Intorpidimento'),
SensationItem(
code: 1,
title: 'Sudorazione intensa'),
SensationItem(
code: 2, title: 'Dolore al petto'),
SensationItem(code: 3, title: 'Nausea'),
SensationItem(code: 4, title: 'Tremori'),
SensationItem(
code: 5,
title: 'Paura di perdere il controllo',
SensationItem(
code: 6,
title: 'Sbandamento / Vertigini'),
SensationItem(
code: 7, title: 'Palpitazioni'),
SensationItem(
code: 8,
title: 'Sensazione di soffocamento'),
];
}
Now I should insert this in a chartBar (from listCodeSensations) as in the next example:
var dataLine = [
addCharts('Formicolio / Intorpidimento', 10), //title of sensations, count
addCharts('Sudorazione intensa', 20), //title of sensations, count
addCharts('Dolore al petto', 5), //title of sensations, count
addCharts('Nausea', 14), //title of sensations, count
addCharts('Tremori', 18), //title of sensations, count
addCharts('Paura di perdere il controllo', 23), //title of sensations, count
addCharts('Sbandamento / Vertigini', 6), //title of sensations, count
addCharts('Palpitazioni', 1), //title of sensations, count
addCharts('Sensazione di soffocamento', 12), //title of sensations, count
];
Code Updated
const names = [
'Formicolio / Intorpidimento',
'Sudorazione intensa',
'Dolore al petto',
'Nausea',
'Tremori',
'Paura di perdere il controllo',
'Sbandamento / Vertigini',
'Palpitazioni',
'Sensazione di soffocamento',
];
class SensationItem {
final int code;
final String title;
SensationItem({this.code, this.title});
}
class AnyClass {
static final sensationList = List<SensationItem>.generate(names.length, (i) => SensationItem(code: i, title: names[i]));
}
class AddCharts {
final String title;
final int count;
AddCharts(this.title, this.count);
}
void main(List<String> args) {
const data = [4, 3, 2, 3, 2, 4, 3, 4, 2, 5, 2, 2, 3, 4, 5, 6, 0, 4, 8, 3, 2, 1];
var summary = <int, int>{};
data.toSet().toList()
..sort()
..forEach((e) => summary[e] = data.where((i) => i == e).length);
var dataline = List<AddCharts>.generate(names.length, (i) => AddCharts(names[i], summary[i] ?? 0));
print(summary);
}
Result:
{0: 1, 1: 1, 2: 6, 3: 5, 4: 5, 5: 2, 6: 1, 8: 1}
I'm trying to fetch some history data from this rest API in a FutureBuilder. It seems the calls are too many to be handled although there must be a way to fetch the data.
A few info about the api call I'm making:
Average server latency: 632ms
Ideal remote api Calls: 5
Endpoint: https://covid-193.p.rapidapi.com/history?country=greece&day=2020-12-27}
Json Response
{
"get": "history",
"parameters": {
"country": "greece",
"day": "2020-12-27"
},
"errors": [],
"results": 1,
"response": [
{
"continent": "Europe",
"country": "Greece",
"population": 10398156,
"cases": {
"new": "+262",
"active": 120572,
"critical": 473,
"recovered": 9989,
"1M_pop": "12994",
"total": 135114
},
"deaths": {
"new": "+46",
"1M_pop": "438",
"total": 4553
},
"tests": {
"1M_pop": "314492",
"total": 3270139
},
"day": "2020-12-27",
"time": "2020-12-27T15:45:07+00:00"
}
]
}
How time scales to 37,9 sec
I'm making 5 API calls for 5 different dates (all 5 days before today) and I'm parsing the data to a Country Object. The call will approximately take 5 x 632ms = 3610ms = 3,6 sec which sounds reasonable for a delay.
But, I have 6 different types of data to parse, for example the total deaths, I need 5 of these calls to make for 1 type, multiply it by 6 and I get a total of 30 calls. Also note that my top level StreamBuilder can be called twice, so I'm ending up with 60 calls which translates to 37,920 ms = 37,9 sec
StreamBuilder called twice and I can't avoid it
Related Post: Streambuilder will be called twice
This is the layout inside my stream builder:
Layouts from Top to Bottom
Calling CountryScreen Widget to create the layout with the first parsed data
StreamBuilder(
stream: bloc.getCountryStream,
builder: (context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
//Do stuff to show the total variables for each box (note this is a call to another endpoint)
return CountryScreen(
country: country,
),
}
)
CountryScreen
Map country // initialized from above
Widget build (context){
return column(children:[
InfoCard(
title: "Total Cases",
iconColor: Color(0xFFFF8C00),
effectedNum: "${country['totalcases']}",
country: country['country'],
searchFor: "Total Cases",
),
InfoCard(...),
...
...
InfoCard(
title: "New Deaths",
iconColor: Colors.red,
effectedNum: "${country['newdeaths']}",
country: country['country'],
searchFor: "Total Cases",
)
]);
}
Info Card
Widget build(context)
{
return Expanded(
child: LineReportChart(
country: country, searchFor: searchFor),
);
}
LineReportChart
class LineReportChart extends StatefulWidget {
final String country;
final String searchFor;
LineReportChart({this.country, this.searchFor});
#override
_LineReportChart createState() =>
_LineReportChart(country: country, searchFor: searchFor);
}
class _LineReportChart extends State<LineReportChart> {
String country;
String searchFor;
_LineReportChart({this.country, this.searchFor});
List<FlSpot> spots = [];
#override
Widget build(BuildContext context) {
return FutureBuilder(
future: getSpots(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if (!snapshot.hasData) {
return AspectRatio(
aspectRatio: 2.2,
child: SizedBox(
child: CircularProgressIndicator(),
));
}
spots = snapshot.data;
return AspectRatio(
aspectRatio: 2.2,
child: LineChart(
LineChartData(
gridData: FlGridData(
show: false,
),
borderData: FlBorderData(
show: false,
),
titlesData: FlTitlesData(show: false),
lineBarsData: [
LineChartBarData(
spots: spots,
isCurved: true,
dotData: FlDotData(show: false),
belowBarData: BarAreaData(show: false),
colors: [kPrimaryColor],
barWidth: 3),
]),
),
);
});
}
Future<dynamic> getSpots() async {
return FetchCountry.getNewCasesChart(country, searchFor);
}
Rest API Call
getNewCasesChart method
static Future<List<FlSpot>> getNewCasesChart(country, searchFor) async {
//do 5 calls and the parsing for each one. I didn't include it as the post is already long.
print('called function for fetch data');
List<FlSpot> chartPoints;
switch (searchFor) {
case "Total Cases":
await Future.delayed(Duration(seconds: 2));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(1, 1),
];
break;
case "Total Deaths":
await Future.delayed(Duration(seconds: 4));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
];
break;
case "Recovered":
await Future.delayed(Duration(seconds: 3));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(3, 2.1),
];
break;
case "New Cases":
await Future.delayed(Duration(seconds: 6));
chartPoints = [
FlSpot(1, 1.5),
FlSpot(0, .5),
FlSpot(2, .5),
];
break;
case "Critical":
await Future.delayed(Duration(seconds: 5));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(3, .5),
FlSpot(5, .5),
];
break;
case "New Deaths":
await Future.delayed(Duration(seconds: 3));
chartPoints = [
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
FlSpot(0, .5),
FlSpot(1, 1.5),
FlSpot(2, .5),
];
break;
default:
}
return chartPoints;
}
Is there any way to reduce the total calls on the top level layout?
I am trying to create a time series chart with tooltips in flutter, but I can't manage to overcome this error message. "Offset argument contained a NaN value. 'dart:ui/painting.dart': Failed assertion: line 43: ''". https://github.com/google/charts/issues/58 is where I got this code from, but nobody else seems to have this issue. The same error message always appears when trying other types of charts and different blocks of code found on that github page. Here is the relevant code:
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:charts_flutter/flutter.dart';
import 'package:charts_flutter/src/text_element.dart' as text;
import 'package:charts_flutter/src/text_style.dart' as style;
class CustomMeasureTickCount extends StatelessWidget {
final List<charts.Series> seriesList;
final bool animate;
static String pointerValue;
CustomMeasureTickCount(this.seriesList, {this.animate});
factory CustomMeasureTickCount.withSampleData() {
return new CustomMeasureTickCount(
_createSampleData(),
animate: false,
);
}
#override
Widget build(BuildContext context) {
return new charts.TimeSeriesChart(seriesList,
animate: animate,
behaviors: [
LinePointHighlighter(symbolRenderer: CustomCircleSymbolRenderer())
],
selectionModels: [
SelectionModelConfig(changedListener: (SelectionModel model) {
if (model.hasDatumSelection)
pointerValue = model.selectedSeries[0]
.measureFn(model.selectedDatum[0].index)
.toString();
})
],
/// Customize the measure axis to have 10 ticks
primaryMeasureAxis: new charts.NumericAxisSpec(
tickProviderSpec:
new charts.BasicNumericTickProviderSpec(desiredTickCount: 10)));
}
/// Create one series with sample hard coded data.
static List<charts.Series<MyRow, DateTime>> _createSampleData() {
final data = [
new MyRow(new DateTime(2017, 9, 25), 6),
new MyRow(new DateTime(2017, 9, 26), 8),
new MyRow(new DateTime(2017, 9, 27), 6),
new MyRow(new DateTime(2017, 9, 28), 9),
new MyRow(new DateTime(2017, 9, 29), 11),
new MyRow(new DateTime(2017, 9, 30), 15),
new MyRow(new DateTime(2017, 10, 01), 25),
new MyRow(new DateTime(2017, 10, 02), 33),
new MyRow(new DateTime(2017, 10, 03), 27),
new MyRow(new DateTime(2017, 10, 04), 31),
new MyRow(new DateTime(2017, 10, 05), 23),
];
return [
new charts.Series<MyRow, DateTime>(
id: 'Cost',
domainFn: (MyRow row, _) => row.timeStamp,
measureFn: (MyRow row, _) => row.cost,
data: data,
colorFn: (_, __) => charts.MaterialPalette.indigo.shadeDefault,
)
];
}
}
/// Sample time series data type.
class MyRow {
final DateTime timeStamp;
final int cost;
MyRow(this.timeStamp, this.cost);
}
class CustomCircleSymbolRenderer extends CircleSymbolRenderer {
#override
void paint(ChartCanvas canvas, Rectangle bounds,
{List dashPattern,
Color fillColor,
FillPatternType fillPattern,
Color strokeColor,
double strokeWidthPx}) {
super.paint(canvas, bounds,
dashPattern: dashPattern,
fillColor: fillColor,
fillPattern: fillPattern,
strokeColor: strokeColor,
strokeWidthPx: strokeWidthPx);
canvas.drawRect(
Rectangle(bounds.left - 5, bounds.top - 30, bounds.width + 10,
bounds.height + 10),
fill: Color.white);
var textStyle = style.TextStyle();
textStyle.color = Color.black;
textStyle.fontSize = 15;
canvas.drawText(
text.TextElement(CustomMeasureTickCount.pointerValue, style: textStyle),
(bounds.left).round(),
(bounds.top - 28).round());
}
}
The error occurs because of an new event occuring like navigating to a new page while the textfield is in foccus. To fox the issue just simply remove focuss from the textfield.
For example
FocusScope.of(context).requestFocus(new FocusNode());