【问题标题】:How to change the state of an particular toggle switch inside the StreamBuilder in flutter如何在颤动中更改 StreamBuilder 中特定切换开关的状态
【发布时间】:2019-03-25 01:05:00
【问题描述】:

我正在使用 Flutter 构建一个学校服务跟踪应用。由于我是移动应用程序开发的新手,我面临着很多错误。其中之一是,

用户登录到应用程序后,在仪表板中,它会在卡片小部件中显示其孩子的个人资料。每个个人资料都作为一个切换开关按钮来更新他们的出勤率。

每当他们点击切换按钮时,数据库中的数据就会更新。但不知道如何更改轻按的切换开关按钮的状态。

我正在使用 Google Firebase Firestore 数据库。

这是我的数据库结构。

Profiles(Children) 表结构。

以下是出勤表结构。每个文档将每天以特定日期的名称创建。在每个文档配置文件中,ids 存储为子集合。

在每个个人资料子集合中,一个文档将在个人资料名称下包含出勤详细信息。

这就是我从数据库中检索数据的方式。

       CustomScrollView(
          slivers: <Widget>[
            SliverList(
              delegate: SliverChildListDelegate([
                whiteLogo(), // this is a logo widget
              ]),
            ),
            StreamBuilder(
              stream: Firestore.instance.collection('profiles').snapshots(),
              builder: (context, snapshot) => SliverList(
                  delegate: SliverChildBuilderDelegate((context, index) =>
                    Container(
                      child: userCard(context, snapshot.data.documents[index]), // profile card
                    ),
                  childCount: snapshot.hasData ? snapshot.data.documents.length : 0,
                ),
              )
            )
          ],
        )

以下是 userCard 小部件

    userCard(BuildContext context, DocumentSnapshot document) {

    var attendanceCollection = Firestore.instance.collection('attendance').document('10-01-2019').collection(document.documentID);

    var documentId = document["name"].toString().toLowerCase();

    var attendanceReference = attendanceCollection.document(documentId);

    bool status = true;


    return Card(
      margin: EdgeInsets.fromLTRB(20.0, 20.0, 20.0, 20.0),
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(10.0)),
      ),
      elevation: 0.3,
      color: Colors.white,
      child: Padding(
        padding: EdgeInsets.fromLTRB(5.0, 15.0, 5.0, 10.0),
        child: Column(
          children: <Widget>[
            ListTile(
              leading: (
                Container(
                  width: 50.0,
                  height: 50.0,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    image: DecorationImage(
                      fit: BoxFit.cover,
                      image: NetworkImage(
                        '${document['avatar']}'
                      )
                    ),
                  ),
                )
              ),
              title: Text(document['name']),
              trailing: Column(
                children: <Widget>[
                  Text(
                    'Absent/Present',
                    style: TextStyle(
                      color: Color(0xff868686),
                      fontSize: 12.0
                    ),
                  ),
                  Switch(value: status, onChanged: (value) {

                    setState(() {
                      status = value;
                    });

                    //onChange the "attendance_status" value is changing

                    Firestore.instance.runTransaction((transaction) async {
                      DocumentSnapshot freshSnap = await transaction.get(attendanceReference);
                      await transaction.update(freshSnap.reference, {
                        "attendance_status": value
                      });
                    });


                  },)
                ],
              ),
            ),
            horizontalLine(),
            textTile('School', 'Class', 13.0, Color(0xff827f7f)),
            Container(margin: EdgeInsets.only(bottom: 10.0)),
            textTile(document['destination'], document['class'], 16.0, Color(0xff424242)),
            horizontalLine(),
            buttonWrap(context, document)
          ],
        ),
      ),
    );
}

这是仪表板的预览。

当我点击切换开关按钮时,它会更新数据库中的值。但不是按钮的状态。按钮状态没有改变。

我通过将status 变量放在initState 中进行测试,但随后状态会影响所有按钮。

我想在用户点击时更改特定切换开关按钮的状态。任何帮助将不胜感激。

  initState() {
    status = true;
    super.initState();
  }

【问题讨论】:

    标签: firebase flutter google-cloud-firestore state toggleswitch


    【解决方案1】:

    在您当前的实现中,开关状态并未反映数据库的值,因为没有订阅正在更新其值的数据。您可以将UserCard 小部件设为无状态,而只需使用StreamBuilder 从出席集合中读取Switch 的值。

    这样的事情应该可以解决问题,您的考勤开关将根据考勤文档设置其状态(如果尚未创建文档,则应将其设置为false

    Column(
      children: <Widget>[
        Text(
          'Absent/Present',
          style: TextStyle(
            color: Color(0xff868686),
            fontSize: 12.0
          ),
        ),
    
        StreamBuilder(
          stream: attendanceReference.snapshots(),
          initialData: null,
          builder: (ctx, snap) {
            return Switch(
              value: snap.data == null ? false : snap.data["attendance_status"],
              onChanged: (value) {
                Firestore.instance.runTransaction((transaction) async {
                  DocumentSnapshot freshSnap = await transaction.get(attendanceReference);
                  await transaction.update(freshSnap.reference, {
                    "attendance_status": value
                  });
                });
              },
            );
          },
        )
    

    【讨论】:

    • 感谢您的快速响应。有一个错误弹出窗口。 Another exception was thrown: type 'DocumentSnapshot' is not a subtype of type 'bool'
    • 是的,很抱歉,赋值有误。尝试查看分配Switch 值的行现在是否更好。
    • 你就是那个男人。它运行良好。出现了一个小错误。在我将检索方法更改为这种方式后,它起作用了。snap.data["attendance_status"]
    • 很高兴听到!我已经更新了答案以反映这一点:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-01
    相关资源
    最近更新 更多