如何在用户添加数据并将其存储到列表视图时更新金额值 flutter

How to update the amount value when the user add data and store it to list view flutter

大家好,我是 Flutter 新手,需要您的帮助。在这种情况下,我可以添加预算并将其检索到列表视图。但现在我正在尝试为每个类别只显示 1 个列表,但计算数量?因此,如果用户添加新预算,金额将被计算并更新到列表视图(使用相同的货币)。如果用户在预算代码中添加预算,任何人都可以帮助我如何列出相同类别但更新金额?请帮忙。谢谢你。对于数据库,我在 firebase

中使用 Firestore

选择预算类别

import 'package:flutter/material.dart';
import 'package:monger_app/localization/localization_constants.dart';
import 'package:monger_app/page/detail.dart';
import 'package:monger_app/theme/colors.dart';

class BudgetSettings extends StatefulWidget {
  @override
  _BudgetSettingsState createState() => _BudgetSettingsState();
}

class _BudgetSettingsState extends State<BudgetSettings> {
  List<Container> categorylist = new List();

  var character=[
    {"name":"Food", "image":"food.png"},
    {"name":"Social-Life", "image":"travel.png"},
    {"name":"Transportation", "image":"transportation.png"},
    {"name":"Beauty", "image":"makeup.png"},
    {"name":"Household", "image":"household.png"},
    {"name":"Education", "image":"education.png"},
    {"name":"Health", "image":"health.png"},
    {"name":"Gift", "image":"gift.png"},
    {"name":"Other", "image":"other.png"},
  ];
  _makelist() async {
    for (var i = 0; i < character.length; i++) {
      final newcharacter = character[i];
      final String image = newcharacter["image"];
      categorylist.add(
        new Container(
          padding: new EdgeInsets.all(20.0),
          child: new Card( child:
              SingleChildScrollView(
                child: new Column(
                      children: <Widget>[
                        new Hero(
                          tag: newcharacter['name'], 
                          child: new Material(
                            child: new InkWell(
                              onTap: ()=> Navigator.of(context).push(new MaterialPageRoute(
                                builder: (BuildContext context)=> new Detail(name: newcharacter['name'], image: image,),

                              )),
                                child:
                                  new Image.asset("assets/$image", fit: BoxFit.contain,),
                                )
                              ),
                              ),

                        //new Image.asset('assets/$image', fit: BoxFit.cover,),
                        new Padding(padding: new EdgeInsets.all(5.0),),
                        new Text(newcharacter['name'], style: new TextStyle(fontSize: 18.0),),
                      ],
                    ),
              ),
            ),
            ),
      );
    }
  }

  @override
  void initState() {
    _makelist();
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: primary,
        title: Text(getTranslated((context), "budget_settings"),

      ),),

      body: new GridView.count(
          crossAxisCount: 2,
          children: categorylist,
      ),
    );
  }
}

添加预算代码

import 'package:dropdownfield/dropdownfield.dart';
import 'package:flutter/material.dart';
import 'package:monger_app/localization/localization_constants.dart';
import 'package:monger_app/page/account.dart';
import 'package:monger_app/page/budgetsettings.dart';
import 'package:monger_app/theme/colors.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class Detail extends StatefulWidget {


  Detail({this.name, this.image});
  final String name;
  final String image;

  @override
  _DetailState createState() => _DetailState();
}

class _DetailState extends State<Detail> {
  @override

  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: AppBar(
        title: Text(getTranslated((context), "budget_settings"),),
        elevation: 0,
        brightness: Brightness.light,
        backgroundColor: primary,
        leading: IconButton(
          onPressed: (){
            Navigator.pop(context, MaterialPageRoute(builder: (context) => Account()));
          },
          icon: Icon(Icons.arrow_back_ios,
            size: 20,
            color: Colors.black,),
        ),
      ),
      body: new ListView(
        children: <Widget>[
          new Container(
              height: 250.0,
              child:
              new Hero(tag: widget.name,
                  child: new Material(
                      child: new InkWell(
                        child: new Image.asset("assets/${widget.image}", fit: BoxFit.contain,),
                      )
                  ))
          ),
          new Name(name: widget.name,),
        ],
      ),
    );
  }
}

class Name extends StatefulWidget {
  Name({this.name});
  final String name;

  @override
  _NameState createState() => _NameState();
}

class _NameState extends State<Name> {
  @override
  String selectCurrency;

  final currencySelected = TextEditingController();
  var _formKey = GlobalKey<FormState>();


  List <String> currencycategories = [
    "IDR",
    "MYR",
    "USD",
    "CNY"
  ];
  Widget build(BuildContext context) {
    final amount = TextEditingController();
    FirebaseFirestore firestore = FirebaseFirestore.instance;
    CollectionReference collect= firestore.collection("Budget");

    final FirebaseAuth _auth = FirebaseAuth.instance;
    final User user =_auth.currentUser;
    final uid = user.uid;

    return Form(
        key: _formKey,
        child: Padding(
          padding: EdgeInsets.all(20.0),
          child: Column(
            children: <Widget>[
              Container(
                  child: Center(
                    child: Column(
                      children: <Widget>[
                        Padding(
                          padding: EdgeInsets.all(20.0),
                          child: Text(
                            widget.name,
                            textAlign: TextAlign.center,
                            style: new TextStyle(
                              fontSize: 25.0,
                              color: primary,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ),
                        Row(
                          children: <Widget> [
                            new Expanded(child: new DropDownField(
                              controller: currencySelected,
                              labelText: getTranslated((context), "currency_hint"),
                              enabled: true,
                              itemsVisibleInDropdown: 4,
                              items: currencycategories,
                              onValueChanged: (dynamic value) {
                                selectCurrency = value;
                              },
                              value: selectCurrency,
                              required: false,
                            ),
                              flex: 2,
                            ),
                            new SizedBox(
                              width: 10.0,
                            ),
                            new Expanded(child: TextFormField(
                              validator: (input) {
                                if (input.isEmpty) return 'Please fill up the text fields';
                              },
                              controller: amount,
                              decoration: InputDecoration(
                                border: OutlineInputBorder(),
                                labelText: getTranslated((context), "budget_enter"),
                                enabledBorder: OutlineInputBorder(

                                  borderSide: BorderSide(color: secondary),
                                ),
                                focusedBorder: OutlineInputBorder(
                                  borderSide: BorderSide(color: secondary),
                                ),
                              ),
                            ),
                              flex: 2,
                            )],
                        ),
                        Padding(
                          padding: EdgeInsets.all(20.0),
                          child: ElevatedButton(

                            onPressed: () async {
                              final FirebaseAuth _auth = FirebaseAuth
                                  .instance;
                              final User user = _auth.currentUser;
                              final uid = user.uid;

                              if(!_formKey.currentState.validate()){
                                return;
                              }
                              _formKey.currentState.save();

                              collect.add({
                                'name': this.widget.name,
                                'currency': selectCurrency,
                                'amount': amount.text,
                              });
                              amount.text = "";
                              Navigator.pop(context);
                            },
                            child: Text(getTranslated((context), "save_button").toUpperCase(), style: TextStyle (
                              fontSize: 14,
                            )),
                            style: ButtonStyle(
                              padding: MaterialStateProperty.all<EdgeInsets>(EdgeInsets.all(20.0)),
                              foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
                              backgroundColor: MaterialStateProperty.all<Color>(Colors.pink),
                              shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                                RoundedRectangleBorder(
                                    borderRadius: BorderRadius.circular(10.0),
                                    side: BorderSide(color: secondary)
                                ),
                              ),
                            ),

                          ),
                        )
                      ],


                    ),
                  )

              )
            ],
          ),
        )
    );
  }
}

检索到列表查看代码

import 'package:flutter/material.dart';
import 'package:monger_app/localization/localization_constants.dart';
import 'package:monger_app/page/transaction.dart';
import 'package:monger_app/theme/colors.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import './transaction.dart' as expense;
import './transaction.dart' as income;

class TransactionMonthly extends StatefulWidget {
  @override
  _TransactionMonthlyState createState() => _TransactionMonthlyState();
}

class _TransactionMonthlyState extends State<TransactionMonthly> with SingleTickerProviderStateMixin {

  TabController controller;
  @override
  void initState() {
    controller = new TabController(vsync: this, length: 2);
    super.initState();
  }
  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(getTranslated(context, 'budget_title'),),
        elevation: 0,
        brightness: Brightness.light,
        backgroundColor: primary,
        leading: IconButton(
          onPressed: (){
            Navigator.pop(context, MaterialPageRoute(builder: (context) => Transactions()));
          },
          icon: Icon(Icons.arrow_back_ios,
            size: 20,
            color: Colors.black,),
        ),
      ),
      body: StreamBuilder(
          stream: FirebaseFirestore.instance.collection('Budget').snapshots(),
          builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
            if (snapshot.hasData) {
              return ListView(
                children: snapshot.data.docs.map((document) {
                  return Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(children: [
                          SizedBox(width: 10,),
                          Text(document.get('name'),style: TextStyle(fontSize: 16,
                              color: primary,
                              fontWeight: FontWeight.w600
                          ),),
                        ],
                        ),
                        SizedBox(height: 10,),
                        Row(children: [
                          SizedBox(width: 10,),
                          Text(document.get('currency'),style: TextStyle(fontSize: 16,
                              color: primary,
                              fontWeight: FontWeight.w600
                          ),),
                          SizedBox(width: 10,),
                          Text(document.get('amount'),style: TextStyle(fontSize: 16,
                              color: primary,
                              fontWeight: FontWeight.w600
                          ),),
                        ],
                        ),
                        SizedBox(height: 8,),
                        Row(
                          mainAxisAlignment: MainAxisAlignment.end,
                          children: [
                            GestureDetector(
                              onTap: (){
                                Widget cancelButton = FlatButton(child: Text("Cancel"),
                                  onPressed: (){
                                    Navigator.pop(context);
                                  },
                                );
                                Widget deleteButton = FlatButton(child: Text("Delete"),
                                  onPressed: (){
                                    FirebaseFirestore.instance.collection('Budget').doc(document.id).delete();
                                    Navigator.pop(context);
                                  },
                                );
                                showDialog(
                                  context: context,
                                  builder: (context) => AlertDialog(
                                    title: Text('Delete Budget'),
                                    content: Text('Are you sure want to delete it?'),
                                    actions: [
                                      cancelButton,
                                      deleteButton,
                                    ],
                                  ),
                                );
                                //_showDeleteDialog();
                                //_showDeleteDialog(document: document);
                              },
                              child: Row(
                                children: [
                                  Icon(Icons.delete_forever_outlined,
                                    color: Colors.red,
                                  ),
                                  SizedBox(width: 6,),
                                  Text('Delete', style: TextStyle(fontSize: 16,
                                      color: Colors.red,
                                      fontWeight: FontWeight.w600
                                  ), ),
                                ],
                              ),
                            )
                          ],
                        )
                      ],)
                  );
                }).toList(),
              );
            }
            return Center(
              child: CircularProgressIndicator(),
            );
          }
      ),
    );
  }
}

我想你想要的是一种按名称分组,这样你就可以在你的例子中用 160 来显示食物类别,而不是同一类别的两倍(如果我错了请纠正我)。我的建议是首先创建一个名为 Budget 的 class 以及您的三个属性 name, currency and amount。当您在 TransactionMonthly Streambuilder 中收到数据时,您需要按名称对快照数据进行分组。完成后,您将创建一个预算列表 List<Budget> budgets,以便您添加每个预算名称的金额总和。

这里有一个示例代码,您可以简单地复制粘贴并在 DartPad 上自行试用:

import 'package:collection/collection.dart';

//DATA coming from your Firebase collection

Map<String, dynamic> data1 = {
  'name':"Food",
  'currency': "IDR",
  'amount': 100,
};


Map<String, dynamic> data2 = {
  'name':"Food",
  'currency': "IDR",
  'amount': 60,
};

Map<String, dynamic> data3 = {
  'name':"Beauty",
  'currency': "USD",
  'amount': 120,
};

//Your Budget class

class Budget{
  String currency;
  String name;
  int amount;
  
  @override
  String toString(){
     return "Budget: {currency: $currency, name: $name, amount: $amount}";
  }
  
  Budget({required this.currency, required this.name, required this.amount});
}



void main(){

  List<Map<String, dynamic>> snapshot = [data1, data2, data3]; 
  List<Budget> budgets = [];

//you group your budgets by name so you will have: {'Food': [data1, data2], 'Beauty':[data3]}

final groupByName = groupBy(snapshot, (Map<String, dynamic> doc)=>doc['name']);
  
  print(groupByName);
  
  int totalAmount = 0;
  String currency = "";
  
  groupByName.forEach((name, value){
    //because we grouped by name every value will have same currency
    currency = value[0]['currency'];

    //Here we calculate the sum of all Food 
    totalAmount = value.map((e)=>e['amount']).reduce((v, e)=> v+e);
    budgets.add(Budget(currency: currency, amount: totalAmount, name: name));
  });
  
 //budgets is your final list to use in your listView
print(budgets);
}