在 Flutter 中的 ListView 中搜索(使用 Firebase 中的数据)

Posted

技术标签:

【中文标题】在 Flutter 中的 ListView 中搜索(使用 Firebase 中的数据)【英文标题】:Search in ListView (with Data from Firebase) in Flutter 【发布时间】:2021-07-24 13:07:38 【问题描述】:

我正在尝试在我的应用中实现搜索功能。现在我有一个 ListView,它将我从 Firebase 数据库获取的数据显示为流。您对如何搜索此列表有任何想法吗?

这是我的 ListView 代码:

import "package:rate_my_food_1/models/imbiss.dart";
import "package:provider/provider.dart";
import "package:rate_my_food_1/widgets/imbiss_tile.dart";

class ImbissList extends StatefulWidget 
  @override
  _ImbissListState createState() => _ImbissListState();


class _ImbissListState extends State<ImbissList> 

  @override
  Widget build(BuildContext context) 
    final imbiss = Provider.of<List<Imbiss>>(context);


    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: InputDecoration(hintText: "Suchen...", hintStyle: TextStyle(color: Colors.white)),
            style: TextStyle(color: Colors.white),
          ),
        ),
        SizedBox(height: 10,),
        Expanded(
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: imbiss.length ?? 0,
            itemBuilder: (context, index)
              return ImbissTile(imbiss: imbiss[index]);
            ,
          ),
        ),
      ],
    );
  

以下是我在应用主屏幕中实现 ListView 的方式:

import 'package:rate_my_food_1/models/imbiss.dart';
import "package:rate_my_food_1/services/database.dart";
import "package:provider/provider.dart";
import "package:rate_my_food_1/widgets/imbiss_list.dart";




class Home extends StatefulWidget 
  @override
  _HomeState createState() => _HomeState();


class _HomeState extends State<Home> 



  @override
  Widget build(BuildContext context) 

    return StreamProvider<List<Imbiss>>.value(
        value: DatabaseService().imbisses,
        child: Scaffold(
          backgroundColor: Colors.grey[800],
          //Add Button
          floatingActionButton: FloatingActionButton(
            onPressed: ()
              Navigator.pushNamed(context, "/add");
            ,
            child: Icon (Icons.add),
            backgroundColor: Colors.cyanAccent,
          ),
          body: Column(
            children: <Widget>[
              SafeArea(child: SizedBox(height: 10.0,)),
              //Imbissliste
              Expanded(child: ImbissList()),
            ],
          )
        )
    );
  

我正在考虑制作第二个列表,我可以在其中仅过滤包含我正在写入 TextField 的内容的对象,但我不知道如何正确地做到这一点。 您对如何在此 ListView 中进行搜索有任何想法吗?

如果您需要我的项目中的更多代码,请告诉我。 感谢所有答案! 优酷

编辑: 这是我的代码 atm,问题是当我启动应用程序时它不显示 ListView 和 TextField:

import "package:rate_my_food_1/models/imbiss.dart";
import "package:provider/provider.dart";
import "package:rate_my_food_1/widgets/imbiss_tile.dart";

class ImbissList extends StatefulWidget 
  @override
  _ImbissListState createState() => _ImbissListState();


class _ImbissListState extends State<ImbissList> 

  List<Imbiss> imbiss = [];
  List<Imbiss> filteredImbiss = [];

  @override
  initState() 
    imbiss = Provider.of<List<Imbiss>>(context);
    filteredImbiss = imbiss;

    super.initState();
  

  @override
  Widget build(BuildContext context) 

    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: InputDecoration(hintText: "Suchen...", hintStyle: TextStyle(color: Colors.white)),
            style: TextStyle(color: Colors.white),
            onChanged: (value) 
              setState(() 
               filteredImbiss = imbiss.where((imbiss) => imbiss.name.contains(value)).toList();
             );
            ,
          ),
        ),
        SizedBox(height: 10,),
        Expanded(
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: filteredImbiss.length,
            itemBuilder: (context, index)
              return ImbissTile(imbiss: filteredImbiss[index]);
            ,
          ),
        ),
      ],
    );
  
`

【问题讨论】:

嘿!您只想过滤已加载的列表吗?还是要动态查询firestore? 动态查询 Firestore 听起来很理想,但我对这两种解决方案都很满意! 【参考方案1】:

我们可以使用 state 中的键过滤检索到的数据。可以使用TextField 小部件中的onChanged(String) 方法更新此密钥。我们只是过滤每个构建的列表,请参见下面的示例:

class ImbissList extends StatefulWidget 
  @override
  _ImbissListState createState() => _ImbissListState();


class _ImbissListState extends State<ImbissList> 
  // The search key to filter the imbisses.
  String key = '';

  @override
  Widget build(BuildContext context) 
    var imbisses = Provider.of<List<Imbiss>>(context);

    // Filter the imbisses using the key.
    imbisses = imbisses.where((imbiss) 
      return imbiss.name.contains(key);
    ).toList();

    return Column(
      children: [
        Padding(
          padding: const EdgeInsets.all(8.0),
          child: TextField(
            decoration: InputDecoration(
              hintText: "Suchen...",
              hintStyle: TextStyle(color: Colors.white)),
            style: TextStyle(color: Colors.white),
            onChanged: (value) 
              // Update the key when the value changes.
              setState(() => key = value);
            ,
          ),
        ),
        SizedBox(
          height: 10,
        ),
        Expanded(
          child: ListView.builder(
            shrinkWrap: true,
            itemCount: imbisses.length,
            itemBuilder: (context, index) 
              return ImbissTile(imbiss: imbisses[index]);
            ,
          ),
        ),
      ],
    );
  

【讨论】:

您好,非常感谢您的快速答复。但是由于某种原因,当我现在启动应用程序时,我得到的只是一个灰屏。它也没有显示 TextField .. 唯一存在的是 floatingActionButton。你知道为什么会这样吗? 嗯,这很奇怪。当我尝试实现上面的小部件时,它工作得很好。 Flutter 会抛出任何错误吗? 我没有收到任何错误。经过反复试验,我发现当我不是在 InitState 中而是直接在 Build Widget 中使用“imbiss = Provider.of>(context);filteredImbiss = imbiss;”初始化列表时它像以前一样工作并向我显示列表和文本字段,但是当我输入内容时没有任何反应.. 没错。这样,列表将在每次构建时初始化(因此当 textField 更新时),因此不会发生任何变化。也许唯一的选择是将Imbisses 作为参数传递给ImbissList 小部件? 你能告诉我怎么做吗? (如果你有时间)【参考方案2】:

嘿,我尝试了同样的事情,但我得到一个空白屏幕,如果可以的话,请你分享源代码。

编辑:我知道我哪里出错了。非常感谢您提供的解决方案,这真的很有帮助

【讨论】:

以上是关于在 Flutter 中的 ListView 中搜索(使用 Firebase 中的数据)的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 动画列表:有条件地添加 ListView 项

Flutter - 另一个 Listview 中的 Listview.builder

在 Flutter 应用程序的 ListView.builder 中添加滚动

在 Flutter 应用程序中的 ListView 滚动上隐藏/关闭键盘

如何在 Flutter 中自动滚动 Listview.separated 中的所有 List Tiles?

Flutter 中 ListView.builder 中的反向列表