首页 > 解决方案 > Flutter/Firestore:按类别显示网格

问题描述

我们正在为一个学校项目创建一个食谱应用程序。

我们使用 Dart/Flutter 作为语言,我们将食谱存储在名为“食谱”的 Firestore 数据库集合中,其中包含成分、评论和方法的子集合。在成分集合中,有一个称为“蛋白质”的字段,其中包含一系列蛋白质(牛肉、猪肉、家禽等)

我已经设法制作了一个大网格视图,它显示了当前存储在数据库中的所有食谱的缩略图,但我们想通过它们的蛋白质将它们设置为类别。我设法为这些类别制作了单独的列表,但它们每个都包含所有的食谱。我现在不知道该往哪个方向搜索数据库然后在页面上显示它们。

这是正在创建的当前列表的代码。

我想以某种方式创建一个搜索函数,该函数将创建一个文档 ID 数组,然后将其用于编译列表,但不知道从哪里开始

我只是想在如何完成而不是代码的方向上获得一些推动。如果你愿意,它的过程。

提前致谢

          child: Container(
        alignment: Alignment.bottomRight,
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height - 100.0,
        child: ListView.builder(
          itemCount: 4,
          itemBuilder: (context, index) => Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Padding(
                padding: EdgeInsets.symmetric(horizontal: 8.0),
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: Text(
                    '${categories[index]}',//displays the protein name (beef
                    style: TextStyle(
                        color: Colors.red,
                        fontWeight: FontWeight.bold,
                        fontSize: 25.0),
                  ),
                ),
              ),
              Container(
                height: 180.0,
                child: StreamBuilder(
                                stream: firestoreDb,
                                builder: (
                                  context,
                                  snapshot,
                                ) {
                                  if (!snapshot.hasData)
                                    return CircularProgressIndicator();
                                  return ListView.builder(
                                      scrollDirection: Axis.horizontal,
                                      itemCount: snapshot.data.docs.length,
                                      itemBuilder: (context, int index) {
                                        return GestureDetector(
                                          child: Card(
                                            elevation: 5,
                                            shape: RoundedRectangleBorder(
                                                borderRadius:
                                                    BorderRadius.circular(10)),
                                            child: TestGridTile(
                                              snapshot: snapshot.data,
                                              index: index,
                                            ),
                                          ),
                                        );
                                      });
                                }),
              ),
            ],
          ),
        ),
      )),

根据要求编辑TestGridTile 代码

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:youth_food_movement/recipe/ui/ingredients_page.dart';

//card that displays the recipe information
class TestGridTile extends StatelessWidget {
  //snapshot of the database
  final QuerySnapshot snapshot;
  final int index;
  const TestGridTile({Key key, this.snapshot, this.index}) : super(key: key);
  static String idNumber;

  @override
  Widget build(BuildContext context) {
    //snaphot of the docs
    // ignore: unused_local_variable
    var snapshotData = snapshot.docs[index];
    var docID = snapshot.docs[index].id;
    String recipeID = docID.toString();

    return Container(
      width: 150,//MediaQuery.of(context).size.width,
      height: 150,//MediaQuery.of(context).size.height * 0.25,
      //get the image URL
      child: FutureBuilder(
          future: _getImageURL(docID),
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              //return the image and make it cover the container
              return GestureDetector(
                child: Image.network(
                  snapshot.data,
                  fit: BoxFit.fill,
                ),
                onTap: () {
                  idNumber = recipeID;
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (BuildContext context) =>
                              IngredientsPage(recipeID)));
                },
              );
            } else {
              return Container(
                  child: Center(
                child: CircularProgressIndicator(),
              ));
            }
          }),
    );
  }

  //method to get the image URL
  Future _getImageURL(var docID) async {
    //declare and instantiate the firebase storage bucket
    final FirebaseStorage storage = FirebaseStorage.instanceFor(
        bucket: 'gs://youth-food-movement.appspot.com');
    //ref string will change so the parameter will be the jpg ID (maybe)
    String downloadURL =
        await storage.ref('recipe_images/$docID').getDownloadURL();
    return downloadURL;
  }
}```
I have attached an image of how it looks currently[![current image][1]][1]


  [1]: https://i.stack.imgur.com/HiaYi.jpg

标签: firebaseflutterdartgoogle-cloud-firestore

解决方案


因为这ingredience是一个collection我们没有得到它的初始数据。你有两个选择:

  1. 因为它现在加载所有食谱,并为每个食谱和每个类别过滤掉不适合其中的食谱,并仅显示适合的食谱。如果您愿意分享更多代码,我可以帮助您. 背后是什么TestGridTile

  2. 通过使用带有 where 子句和arrayContaines. 但是为此,该数组proteins不能嵌套在ingredience您正在过滤的集合的子集合中。

proteines如果您将数组移动到doc集合中,recipes这两者都会容易得多。您可以使用客户端代码甚至 Firebase Cloud Functions 来做到这一点。


推荐阅读