颤动细节搜索功能

时间:2020-06-12 08:56:30

标签: firebase flutter search dart gridview

我目前有一个Flutter应用,可在gridview中显示可点击的图像。

Categories

选择图像后,将带您到详细页面,该页面提供有关所选类别的更多信息:

Category Detail

我现在需要构建搜索功能,该功能将根据“类别详细信息”进行过滤。 因此,如果我搜索“钓鱼”,则Gridview过滤器将显示“农业”以及任何其他“类别”详细信息都包含该单词。

当前,每当用户选择“类别”时,我都会使用Firebase返回“类别”详细信息,因此我认为搜索必须链接到我的Firebase吗?

我尝试在网上寻找答案,但没有一个能满足我的特定要求。

更新 包含的Gridview页面代码:

class _LevelPageState extends State<LevelPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: AppBar(
          backgroundColor: Colors.grey,
          title: Text(widget.level.data["region"]),
          centerTitle: true,
        ),
        body: ListView(shrinkWrap: true, children: <Widget>[
          Container(
            child: ListTile(
              title: Text(
                'Current Level ' + widget.level.data["level"].toString(),
                style: TextStyle(
                     color: widget.level.data["level"] == 5
                         ? Colors.red[900]
                         : widget.level.data["level"] == 4
                             ? Colors.orange[900]
                             : widget.level.data["level"] == 3
                                 ? Colors.brown[300]
                                 : widget.level.data["level"] == 2
                                     ? Colors.blue[300]
                                     : widget.level.data["level"] == 1
                                         ? Colors.green[300]
                                         : Colors.black,
                    fontSize: 25,
                    fontWeight: FontWeight.bold),
                textAlign: TextAlign.center,
              ),
            ),
          ),
          Container(
            height: (MediaQuery.of(context).size.height),
            padding: EdgeInsets.all(10),
            child: GridView.count(
              shrinkWrap: true,
              physics: ScrollPhysics(),
              mainAxisSpacing: 40,
              crossAxisSpacing: 20,
              crossAxisCount: 3,
              childAspectRatio: MediaQuery.of(context).size.height / 400,
              children: <Widget>[
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child: Image.asset('assets/images/mediaicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Media',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        },
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Media',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child: Image.asset('assets/images/mobileanditicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Info and Comms',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        },
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Info and Comms',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child: Image.asset('assets/images/utilitiesicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Utilities',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        }, 
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Utilities',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child: Image.asset('assets/images/educationicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Education',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        },
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Education',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child: Image.asset('assets/images/repairsicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Repairs',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        },
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Repairs',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
                ListTile(
                  title: Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(30),
                        color: Colors.grey,
                      ),
                      child: InkWell(
                        enableFeedback: true,
                        child:
                            Image.asset('assets/images/domestichelpicon.png'),
                        onTap: () => {
                          Navigator.of(context).push(MaterialPageRoute(
                              builder: (context) => CategoryPage(
                                  text1: 'Domestic Help',
                                  text2: widget.level.data["region"].toString(),
                                  text3:
                                      widget.level.data["level"].toString())))
                        },
                        splashColor: Colors.white,
                        borderRadius: BorderRadius.circular(20),
                      )),
                  subtitle: Text('Domestic Help',
                      style: TextStyle(
                        color: Colors.white,
                        fontSize: 10,
                      ),
                      textAlign: TextAlign.center),
                ),
              ],
            ),
          ),
        ]));
  }
}

我已将上面的代码调整为仅包含6张gridview图像,以缩短代码。

Firebase上的数据结构: Firebase Data Structure

1 个答案:

答案 0 :(得分:2)

因此,您必须使用将来的构建器包装代码,该构建器将首先等待Firebase中的数据。

然后,您必须显示任何满足您条件的GridView项(字符串包含用户键入的内容,此处为常量:categorySearched)。另外,您可能想要添加下层方法以使其不区分大小写。

您将为此目的使用gridview.builder。

然后,您还需要用相应的图标映射每个类别: Map imageMap = {'Education':'educationicon','Business':'businessicon'}; //等。

希望您应该能够在这里和那里进行一些小的调整就能使您的代码完全正常工作。让我知道您是否需要更多帮助。

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

class LevelCategoryMap {
  final String title;
  final String level;
  final String region;

  LevelCategoryMap(this.title, this.level, this.region);

  Map<String, dynamic> toMap() {
    return {
      'title': title,
      'level': level,
      'description': region
    };
  }

  @override
  String toString() {
    return 'LevelCategoryMap{level: $level, description: $region';
  }
}

class _LevelPageState extends State<LevelPage> {
  final String categorySearched = "fishing";
  String level = 1;

  @override
  Widget build(BuildContext context) {
    final dbCollectionSnapshot = Firestore
        .instance
        .collection("Level$level")
        .where('desc', )
        .snapshots(); // retrieve

    return StreamBuilder<QuerySnapshot>(
        stream: dbCollectionSnapshot,
        builder: (context, snapshot) {
          List<LevelCategoryMap> levelCategory;
          if (!snapshot.hasData || snapshot.data == null) return CircularProgressIndicator();
            snapshot.data.documents.forEach((element) {
              levelCategory.add(LevelCategoryMap(element.documentID, level, element.data['desc']));
            })
            final int resultsLen = levelCategory.length;
            return new Scaffold(
                appBar: AppBar(
                  backgroundColor: Colors.grey,
                  title: Text(widget.level.data["region"]),
                  centerTitle: true,
                ),
                body: ListView(shrinkWrap: true, children: <Widget>[
                  Container(
                    child: ListTile(
                      title: Text(
                        'Current Level ' + widget.level.data["level"].toString(),
                        style: TextStyle(
                            color: widget.level.data["level"] == 5
                                ? Colors.red[900]
                                : widget.level.data["level"] == 4
                                ? Colors.orange[900]
                                : widget.level.data["level"] == 3
                                ? Colors.brown[300]
                                : widget.level.data["level"] == 2
                                ? Colors.blue[300]
                                : widget.level.data["level"] == 1
                                ? Colors.green[300]
                                : Colors.black,
                            fontSize: 25,
                            fontWeight: FontWeight.bold),
                        textAlign: TextAlign.center,
                      ),
                    ),
                  ),

                  Center(
                      child: GridView.builder(
                          itemCount: resultsLen,
                          gridDelegate:
                          SliverGridDelegateWithFixedCrossAxisCount(
                              crossAxisCount: 2),
                          itemBuilder: (context, index) {
                            final String description = levelCategory[index].region;
                            if (description.contains(categorySearched))
                              return myGridItem(context, index, levelCategory[index]);
                            //: ClassifiedThumbnail(connection, capitalize(widget.city), snapshot.data[index]);
                          })),
                ]));
          }

          else
            return CircularProgressIndicator();

        });
  }
}


Widget myGridItem(context, index, LevelCategoryMap myLevelCategory) {
  Map<String, String> imageMap = {'Education': 'educationicon', 'Business': 'businessicon'}; // etc.

  return ListTile(
    title: Container(
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(30),
          color: Colors.grey,
        ),
        child: InkWell(
          enableFeedback: true,
          child: Image.asset('assets/images/' + imageMap[myLevelCategory.title]  + '.png'),
          onTap: () => {
            Navigator.of(context).push(MaterialPageRoute(
                builder: (context) => CategoryPage(
                    text1: myLevelCategory.title, // I assume level is the name with education
                    text2: myLevelCategory.region,
                    text3: myLevelCategory.level)))
          },
          splashColor: Colors.white,
          borderRadius: BorderRadius.circular(20),
        )),
    subtitle: Text(myLevelCategory.title,
        style: TextStyle(
          color: Colors.white,
          fontSize: 10,
        ),
        textAlign: TextAlign.center),
  );

这将与firebase一起使用。但是请注意,您正在下载的一切都在移动设备上完成。在您的情况下,这没什么大不了的,因为您只有10个类别且仅包含文本。但是,如果您想在Firebase中进行基于搜索的查询,则必须使用此处所述的第三方服务:https://firebase.google.com/docs/firestore/solutions/search