Search code examples
firebasefluttergoogle-cloud-firestoreflutter-pageview

How to make each doc of a Firebase collection as ListTile?


I have a code to display a list of images in a PageView with dots navigation. But for my project, I need to display several fields of the same document and this for each document of my Firebase collection. It seems that I need to put all my document as a List, don't know how to do that and can not figure out how to get each field of my doc then... Someone would have any idea ?

This is the code I use to display a list of images :

class SwipeImages extends StatefulWidget {

  final List imageList;

  const SwipeImages({
    Key? key,
    required this.imageList,
  }) : super(key: key);

  @override
  _SwipeImagesState createState() => _SwipeImagesState();

}

class _SwipeImagesState extends State<SwipeImages> {
  
  int _selectedPage = 0;

  @override
  Widget build(BuildContext context) {

    return Container(
      height: 500,
      width: 500,
      child: ClipRRect(
        borderRadius: BorderRadius.circular(20),
        child: Stack(
          children: [

            PageView(
              onPageChanged: (num) {
                setState(() {
                  _selectedPage = num;
                });
              },
              children: [

                for(var i=0; i < widget.imageList.length; i++)
                Container(
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.circular(20),
                    ),
                    child: Image.network(
                      "${widget.imageList[i]}",
                      fit: BoxFit.cover,
                    ), 
                  ),
                ),

              ]
            ),

            Positioned(
              bottom: 20,
              right: 0,
              left: 0,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [

                  for(var i=0; i < widget.imageList.length; i++)
                  AnimatedContainer(
                    duration: Duration(
                      milliseconds: 300
                    ),
                    curve: Curves.easeInOutCubic,
                    width: _selectedPage == i ? 30.0 : 10.0,
                    height: 10.0,
                    margin: EdgeInsets.symmetric(
                      horizontal: 5,
                    ),
                    decoration: BoxDecoration(
                      color: Black.withOpacity(0.4),
                      border: Border.all(
                        width: 0.25,
                        color: Black.withOpacity(0.6)
                      ),
                      borderRadius: BorderRadius.circular(10)
                    ),
                  ),

                ],
              ),
            ),

          ]
        ),
      ),
    );

  }

}


class DisplayImages extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    CollectionReference images = firestore.collection('Images');

    return FutureBuilder(
      future: product.doc('My Document').get(),
      builder: (context, AsyncSnapshot<DocumentSnapshot> snapshot) {

        if(snapshot.connectionState == ConnectionState.done) {

          DocumentSnapshot<Object?> data = snapshot.data!;
          List images = data['Images'];
          // The field is an array with urls of the images I want to display;

          return SwipeImages(imageList: images);

        }
      }
    );
  }
}

Solution

  • keeping it simple, why don't you pass the whole document you get from the FutureBuilder(). This way, you can access all your fields(considering you have model classes, if not then you'll have to access fields using the .data) without having to make a network call again.

    Something like this,

     DocumentSnapshot<Object?> data = snapshot.data!;
             
              return SwipeImages(doc: data);//now you can use the whole separate doc and access all the fields.
    

    If you need a constant stream of documents (multiple documents), then you'll have to use a stream. More info on https://dart.dev/tutorials/language/streams

    Using Streambuilder -

     StreamBuilder(
        stream: stream,
        builder: (BuildContext context,
            AsyncSnapshot<List<DocumentSnapshot>> snapshots) {
          if (snapshots.connectionState == ConnectionState.active &&
              snapshots.hasData) {
            print(snapshots.data);
            return ListView.builder(
              itemCount: snapshots.data.length,
              itemBuilder: (BuildContext context, int index) {
                DocumentSnapshot doc = snapshots.data[index];
               
                return Text(
                  " Do anything with the stream of data",
                );
              },
            );
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),