Flutter Making ReorderableListView Actually Reorder with data from a Firebase Data Stream

98 views Asked by At

I'm having trouble with coding the ability to reorder items in my ReorderableListView widget. The items are pulled from a Firebase collection and displayed on the screen. The problem happens when you try to reorder any of the items.

I was able to successfully use logic for my ReorderableListView from here when I was using a List in the past. I attempted to use that same logic on the stream that I created from Firebase with no luck. I also saw an answer here but I'm confused on the solution since I'm new to Firebase and streams in general.

Having the ability to reorder items and their values keep the correct order after a redorder is what I'm looking for here. I have pasted a gif of the problem, the code, and my Firebase documents. Does anyone have a best practice solution as to how to achieve this result?

The Problem

ReorderableListView Not Keeping New Reorder

breakfast.dart

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';

class Breakfast extends StatefulWidget {
  final String food;
  final String title;

  const Breakfast({super.key, required this.food, required this.title});

  @override
  State<Breakfast> createState() => _BreakfastState();
}

class _BreakfastState extends State<Breakfast> {
  final Stream<QuerySnapshot> _dataStream = FirebaseFirestore.instance
      .collection('data')
      .where('meal', isEqualTo: 'Breakfast')
      .snapshots();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: BoxDecoration(color: Colors.grey[350]),
        child: Column(
          children: [
            Expanded(
              child: StreamBuilder<QuerySnapshot>(
                stream: _dataStream,
                builder: (BuildContext context,
                    AsyncSnapshot<QuerySnapshot> snapshot) {
                  if (snapshot.hasError) {
                    return const Text('Something went wrong');
                  }

                  if (snapshot.connectionState == ConnectionState.waiting) {
                    return const Text("Loading");
                  }

                  return ReorderableListView(
                    autoScrollerVelocityScalar: 100,
                    padding: const EdgeInsets.symmetric(horizontal: 10),
                    onReorder: (int oldIndex, int newIndex) {
                      //HELP NEEDED HERE!
                      // setState(
                      //   () {
                      //     if (oldIndex < newIndex) {
                      //       newIndex -= 1;
                      //     }
                      //     final item = snapshot!.data.docs.removeAt(oldIndex);
                      //     snapshot!.data.docs.insert(newIndex, item);
                      //   },
                      // );
                    },
                    children:
                        snapshot.data!.docs.map((DocumentSnapshot document) {
                      Map<String, dynamic> data =
                          document.data()! as Map<String, dynamic>;
                      return Card(
                        key: Key(document.id),
                        color: Colors.grey[200],
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                        child: InkWell(
                          onTap: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (context) => Breakfast(
                                  food: data['text'],
                                  title: 'Breakfast',
                                ),
                              ),
                            );
                          },
                          child: Row(
                            children: [
                              Expanded(
                                flex: 6,
                                child: SizedBox(
                                  height: 50,
                                  child: Container(
                                    alignment: Alignment.center,
                                    child: Text(data['text'],
                                        style: const TextStyle(fontSize: 20)),
                                  ),
                                ),
                              ),
                              const Padding(
                                padding: EdgeInsets.fromLTRB(0, 0, 25, 0),
                              ),
                            ],
                          ),
                        ),
                      );
                    }).toList(),
                  );
                },
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Firebase Documents

There are 5 documents in the collection. Each document has the same format, with a meal field and a text field. Firebase Document Collection

0

There are 0 answers