Как изменить состояние определенного тумблера внутри StreamBuilder в флаттере - PullRequest
2 голосов
/ 25 марта 2019

Я создаю приложение для отслеживания школьных услуг, используя Flutter.Поскольку я новичок в разработке мобильных приложений, я сталкиваюсь с множеством ошибок.Один из них,

После того, как пользователь вошел в приложение, на панели инструментов он покажет свои дочерние профили в виджете карты.Каждый профиль в виде кнопки тумблера для обновления их посещаемости.

Каждый раз, когда они нажимают на кнопку переключателя, данные обновляются в базе данных.Но не знаю, как изменить состояние нажатой кнопки тумблера.

Я использую базу данных Google Firebase Firestore.

Это моя структура базы данных.

Профили (Структура таблицы детей.

Profiles(children) table structure

Ниже приведена структура таблицы посещаемости.Каждый документ будет создаваться ежедневно под именем определенной даты.Внутри каждого профиля документа идентификаторы хранятся как вложенные коллекции.

Attendance table structure

Внутри каждой подколлекции профиля документ будет иметь данные о посещаемости под именем профиля.

enter image description here

Вот как я извлекаю данные из базы данных.

       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)
          ],
        ),
      ),
    );
}

Это предварительный просмотр панели инструментов.

user dashboard

Когда я нажимаю на кнопку тумблера, он обновляет значение в базе данных.Но не состояние кнопки.Состояние кнопки не меняется.

Я проверил, поместив переменную status внутри initState, но затем состояние влияет на все кнопки.

Я хочу изменить состояние определенной кнопки тумблера, когда пользователь нажимает на нее.Любая помощь будет высоко ценится.

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

1 Ответ

1 голос
/ 25 марта 2019

В вашей текущей реализации состояние переключателя не отражает значение базы данных, так как нет подписки на данные, которые обновляют ее значение.Вы можете сделать виджет UserCard без сохранения состояния и просто прочитать значение Switch из коллекции посещаемости с помощью StreamBuilder.

Что-то вроде этого должно помочь, и ваш переключатель посещаемости установит его состояниев зависимости от документа посещаемости (и он должен быть установлен на 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
              });
            });
          },
        );
      },
    )
...