firebase - 如何在flutter中从firestore开发饼图
问题描述
我是 Flutter 的新手,我想制作饼图,但它必须显示存储在 Firestore 中的类别。如何根据存储在 Firestore 中的“类别”显示饼图?任何人都可以帮忙吗?谢谢
在这段代码中,我仍然使用示例数据来存储饼图。我想根据存储在 Firestore 中的数据来更改它。
代码
import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
//import 'package:cloud_firestore/cloud_firestore.dart';
class StatisticsExpense extends StatefulWidget {
@override
_StatisticsExpenseState createState() => _StatisticsExpenseState();
}
class _StatisticsExpenseState extends State<StatisticsExpense> {
int key = 0;
Map<String, double> dataMap = {
"Food": 5,
"Health": 3,
"Social Life": 2,
};
List<Color> colorList = [
Colors.red,
Colors.yellow,
Colors.green,
];
Widget pieChartExampleOne(){
return PieChart(
key: ValueKey(key),
dataMap: dataMap,
initialAngleInDegree: 0,
animationDuration: Duration(milliseconds: 2000),
chartType: ChartType.ring,
chartRadius: MediaQuery.of(context).size.width / 3.2,
ringStrokeWidth: 32,
colorList: colorList,
chartLegendSpacing: 32,
chartValuesOptions: ChartValuesOptions(
showChartValuesOutside: true,
showChartValuesInPercentage: true,
showChartValueBackground: true,
showChartValues: true,
chartValueStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black
)
),
centerText: 'Expense',
legendOptions: LegendOptions(
showLegendsInRow: false,
showLegends: true,
legendShape: BoxShape.rectangle,
legendPosition: LegendPosition.right,
legendTextStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
)
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 50,),
pieChartExampleOne(),
],
),
)
);
}
}
解决方案
我希望您已经在 Flutter 项目中完成了基本的 Firebase 设置。
首先,为费用创建一个模型:
class Expense {
String amount;
String category;
String date;
String description;
Expense(
{required this.amount,
required this.category,
required this.date,
required this.description});
}
创建一个方法来获取类别及其计数的地图
late List<Expense> _expense = [];
Map<String, double> getCategoryData() {
Map<String, double> catMap = {};
for (var item in _expense) {
print(item.category);
if (catMap.containsKey(item.category) == false) {
catMap[item.category] = 1;
} else {
catMap.update(item.category, (int) => catMap[item.category]! + 1);
// test[item.category] = test[item.category]! + 1;
}
print(catMap);
}
return catMap;
}
然后创建一个流来获取 firbase 集合:
final Stream<QuerySnapshot> expStream =
FirebaseFirestore.instance.collection('TransactionExpense').snapshots();
使用“StreamBuilder”扭曲 Pichart 小部件并设置流:
StreamBuilder<Object>(
stream: expStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("something went wrong");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
final data = snapshot.requireData;
print("Data: $data");
getExpfromSanapshot(data);
return pieChartExampleOne();
},
),
创建一个将快照数据转换为元素列表的方法:
void getExpfromSanapshot(snapshot) {
if (snapshot.docs.isNotEmpty) {
_expense = [];
for (int i = 0; i < snapshot.docs.length; i++) {
var a = snapshot.docs[i];
// print(a.data());
Expense exp = Expense.fromJson(a.data());
_expense.add(exp);
// print(exp);
}
}
}
通过这样做,您可以获得firestore数据并将其绘制在pichat中,这将是实时的(因为StreamBuilder,一旦数据更新到firebase,Pichart就会更新)
完整代码:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:pie_chart/pie_chart.dart';
class StatisticsExpense extends StatefulWidget {
@override
_StatisticsExpenseState createState() => _StatisticsExpenseState();
}
class _StatisticsExpenseState extends State<StatisticsExpense> {
int key = 0;
late List<Expense> _expense = [];
Map<String, double> getCategoryData() {
Map<String, double> catMap = {};
for (var item in _expense) {
print(item.category);
if (catMap.containsKey(item.category) == false) {
catMap[item.category] = 1;
} else {
catMap.update(item.category, (int) => catMap[item.category]! + 1);
// test[item.category] = test[item.category]! + 1;
}
print(catMap);
}
return catMap;
}
List<Color> colorList = [
Color.fromRGBO(82, 98, 255, 1),
Color.fromRGBO(46, 198, 255, 1),
Color.fromRGBO(123, 201, 82, 1),
Color.fromRGBO(255, 171, 67, 1),
Color.fromRGBO(252, 91, 57, 1),
Color.fromRGBO(139, 135, 130, 1),
];
Widget pieChartExampleOne() {
return PieChart(
key: ValueKey(key),
dataMap: getCategoryData(),
initialAngleInDegree: 0,
animationDuration: Duration(milliseconds: 2000),
chartType: ChartType.ring,
chartRadius: MediaQuery.of(context).size.width / 3.2,
ringStrokeWidth: 32,
colorList: colorList,
chartLegendSpacing: 32,
chartValuesOptions: ChartValuesOptions(
showChartValuesOutside: true,
showChartValuesInPercentage: true,
showChartValueBackground: true,
showChartValues: true,
chartValueStyle:
TextStyle(fontWeight: FontWeight.bold, color: Colors.black)),
centerText: 'Expense',
legendOptions: LegendOptions(
showLegendsInRow: false,
showLegends: true,
legendShape: BoxShape.rectangle,
legendPosition: LegendPosition.right,
legendTextStyle: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.black,
)),
);
}
@override
Widget build(BuildContext context) {
final Stream<QuerySnapshot> expStream =
FirebaseFirestore.instance.collection('TransactionExpense').snapshots();
void getExpfromSanapshot(snapshot) {
if (snapshot.docs.isNotEmpty) {
_expense = [];
for (int i = 0; i < snapshot.docs.length; i++) {
var a = snapshot.docs[i];
// print(a.data());
Expense exp = Expense.fromJson(a.data());
_expense.add(exp);
// print(exp);
}
}
}
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 50,
),
StreamBuilder<Object>(
stream: expStream,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text("something went wrong");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
}
final data = snapshot.requireData;
print("Data: $data");
getExpfromSanapshot(data);
return pieChartExampleOne();
},
),
],
),
),
);
}
}
class Expense {
String amount;
String category;
String date;
String description;
Expense(
{required this.amount,
required this.category,
required this.date,
required this.description});
factory Expense.fromJson(Map<String, dynamic> json) {
return Expense(
amount: json['amount'],
category: json['category'],
date: json['date'],
description: json['description'],
);
}
}
// Sample data for PiChart
Map<String, double> dataMap = {
"Food": 4,
"Health": 3,
"Social Life": 2,
};
// Sample data for Expense list
List<Expense> getExpenseList() {
final List<Expense> chartData = [
Expense(
amount: "RM100",
category: "Food",
date: "Jan 15, 2021",
description: "Break fast"),
Expense(
amount: "RM200",
category: "Health",
date: "Feb 15, 2021",
description: "Workout"),
Expense(
amount: "RM200",
category: "Health",
date: "Feb 15, 2021",
description: "Workout"),
Expense(
amount: "RM45",
category: "Health",
date: "Feb 25, 2021",
description: "Workout"),
Expense(
amount: "RM80",
category: "Social Life",
date: "Feb 26, 2021",
description: "Social Media"),
];
return chartData;
}
推荐阅读
- php - 我在 cPanel 上放了 cron 作业命令,但它不起作用
- python - 如何将 __init__ 参数传递给使用 qmlRegisterType 注册的类?
- tfs-2015 - 如何使用户能够在 Backlog 视图中添加功能
- javascript - VueJS 没有正确交互我的数据?
- python-2.7 - 从 Try 函数返回值的问题
- scala - .createOrReplaceTempView & .as 创建查询临时视图的区别
- python - Python 命令提示符 - 自动提取链接
- python - 如何将一个变量中包含的文本与另一个变量匹配
- sql - Postgresql:STRING_AGG() 按未显示值排序的最佳方式
- javascript - 单击按钮将数据保存到文件并关闭窗口