LoginSignup
0
0

More than 1 year has passed since last update.

[Flutter]Cloud Firestoreからデータ一覧を取得してGridViewに表示する

Last updated at Posted at 2023-01-12

非同期でFirestoreから取得したデータを一覧で表示するための実装について記事を書いていきたいと思います。データを一覧で表示する方法については、FlutterのGridViewウィジェットを利用する実装で紹介したいと思います。

Firestoreのデータ構造

今回の記事で紹介するFirestoreのデータ構造は以下のとおりです。
Collectionの中にドキュメントが一覧であり、各ドキュメントはtitleを持っています。
Firestoreデータ構造Sample.png

全体の実装

最初に全体の実装ですが、以下のようになります。
この後の章で要点について解説していきます。

class SakeGridViewWidget extends StatelessWidget {
  final Color color;
  final String title;

  const SakeGridViewWidget({Key? key, required this.color, required this.title}) : super(key: key);

  @override
  Widget build(BuildContext context) {

    var assetsImage = "images/ic_sake.png";
    return MaterialApp(
      title: 'Grid List',
      home: Scaffold(
        body: StreamBuilder(
          stream: FirebaseFirestore.instance.collection('BrandList').snapshots(),
          builder: (BuildContext context,
            AsyncSnapshot<QuerySnapshot> snapshot) {
            if (!snapshot.hasData) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            }

            return GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  crossAxisSpacing: 10.0, // 縦
                  mainAxisSpacing: 10.0, // 横
                  childAspectRatio: 0.7),
              itemCount: snapshot.data!.docs.length,
              padding: const EdgeInsets.all(5.0),
              itemBuilder: (BuildContext context, int index) {
                return Container(
                  child: GestureDetector(
                    child: Column(
                      children: <Widget>[
                        Image.asset(assetsImage, fit: BoxFit.cover,),
                        Container(
                          margin: const EdgeInsets.all(10.0),
                          child: Text(snapshot.data!.docs[index]['title']),
                        ),
                      ],
                    )),
                  padding: const EdgeInsets.all(10.0),
                  decoration: BoxDecoration(
                    color: color,
                    boxShadow: const [
                      BoxShadow(
                        color: Colors.grey,
                        offset: Offset(5.0, 5.0),
                        blurRadius: 10.0,
                      )
                    ],
                  ),
                );
              },
            );
          }),
      ),
    );
  }
}

Documentの一覧を非同期で取得する

Firestoreからデータの一覧を取得する場合、Collectionに対してスナップショットを取得する形となります。
スナップショットは非同期で取得する事になり、返り値はStream<QuerySnapshot<T>>型となっているため、StreamBuilderウィジェットを利用して取得します。

        body: StreamBuilder(
          stream: FirebaseFirestore.instance.collection('BrandList').snapshots(),

データ取得中のインジケータの表示

非同期でのデータ取得中であることがわかるように、取得中の間だけインジケータを表示する実装は以下の部分になります。データ取得が完了するとsnapshotに値が入ることでif文を抜けられます。

          builder: (BuildContext context,
            AsyncSnapshot<QuerySnapshot> snapshot) {
            if (!snapshot.hasData) {
              return const Center(
                child: CircularProgressIndicator(),
              );
            }

タイル状にデータを一覧表示

縦に3列のタイル状になるようにデータをGridViewに表示する実装は以下の部分になります。

            return GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                  crossAxisCount: 3,
                  crossAxisSpacing: 10.0, // 縦
                  mainAxisSpacing: 10.0, // 横
                  childAspectRatio: 0.7),
              itemCount: snapshot.data!.docs.length,
              padding: const EdgeInsets.all(5.0),

各パラメータの意味は以下となります。
crossAxisCount:縦に何列並べるかの設定
crossAxisSpacing:縦の並びの余白
mainAxisSpacing:横の並びの余白
childAspectRatio:1つのタイルの縦横比率
itemCount:表示するデータの個数
padding:GridViewの周りの余白

Documentデータを各タイルに表示する

GridViewの各タイルにデータを表示する実装は以下の部分になります。

              itemBuilder: (BuildContext context, int index) {
                return Container(
                  child: GestureDetector(
                    child: Column(
                      children: <Widget>[
                        Image.asset(assetsImage, fit: BoxFit.cover,),
                        Container(
                          margin: const EdgeInsets.all(10.0),
                          child: Text(snapshot.data!.docs[index]['title']),
                        ),
                      ],
                    )),

assetsImageはサンプルのイメージ画像を表示しています。
Container部分が、コレクションのスナップショットから各Documentのtitleフィールドのデータの取得する処理となっています。itemBuilderの引数でもらっているindexが1つ1つのDocumentデータにアクセスするインデックスとなっています。
2次元配列のようなアクセス方法が可能で、
snapshot.data!.docs[0]['title']ならabcDoctitle
snapshot.data!.docs[1]['title']ならbcdDoctitle
・・・とアクセスできます。

さいごに

私がFlutterを学ぶにあたり、参考にしたサイト集を別の記事でまとめていますので、こちらも是非読んでみてもらえたらと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0