使用 Provider 和模型类搜索/过滤 ListView

2023-11-29

我想通过在搜索字段中输入的文本来过滤列表视图。在线和本网站上有很多示例,但所有内容都过于简化,所有内容都在一个有状态的小部件中,和/或看起来有点混乱,可能不是构建事物的最佳方式。我有一个简单的应用程序,它使用 Provider、一个模型类(Dog)和一个 Dogs 类,其中包含我正在使用的列表。

目标:通过输入的文本过滤狗列表。

狗模型

class Dog {
  final String breed;
  final String name;
  final int age;

  Dog({this.breed, this.name, this.age});
}

犬类

import 'package:flutter/cupertino.dart';
import 'dart:collection';

import '../models/dog.dart';

class Dogs extends ChangeNotifier {
  final List<Dog> _myDogs = [
    Dog(name: 'Mackie', age: 8, breed: 'Rottweiler'),
    Dog(name: 'Riley', age: 8, breed: 'Rottweiler'),
    Dog(name: 'Tank', age: 7, breed: 'Mastiff'),
    Dog(name: 'Tanner', age: 7, breed: 'Mastiff'),
    Dog(name: 'Rocky', age: 10, breed: 'Rottweiler'),
    Dog(name: 'Angel', age: 11, breed: 'Poodle'),
    Dog(name: 'Roxie', age: 8, breed: 'St. Bernard'),
    Dog(name: 'Spud', age: 8, breed: 'St. Bernard'),
    Dog(name: 'Nick', age: 4, breed: 'Rottweiler'),
  ];

  UnmodifiableListView<Dog> get dogs => UnmodifiableListView(_myDogs);
}

主要使用 ListView

import 'package:flutter/material.dart';

import 'package:provider/provider.dart';
import 'providers/dogs.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Dogs(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _controller = TextEditingController();
  String _searchText;

  @override
  void initState() {
    _controller.addListener((){
      setState(() {
        _searchText = _controller.text;
      });
    },);
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dogs',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dogs'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                hintText: "Search",
                prefixIcon: Icon(Icons.search),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(4.0),
                  ),
                ),
              ),
              onChanged: (value){
                //TODO when text is entered into search bar
              },
            ),
            Consumer<Dogs>(
              builder: (context, dogData, child) => Expanded(
                child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: dogData.dogs.length,
                    itemBuilder: (context, index) => Card(
                          elevation: 3,
                          child: ListTile(
                            title: Text(dogData.dogs[index].name),
                          ),
                        )),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

经过几次迭代,根据我从网上找到的信息,我已经停止并清理了这一点。

我的列表视图显示狗,并且有我的 TextField 我正在使用有状态小部件,因此我可以使用 init 作为 TextController 监听器,并在完成后处理它 我的文本控制器是使用控制器设置的,我正在初始化一个变量,该变量将搜索文本保存到controller.text 我相当确定我需要使用 TextField 的 onChanged 来通过我的搜索工具使用该值(以某种方式)

目前,我的列表视图构建器正在根据dogData.dogs.length获取列表,但这不包含过滤内容的逻辑,因为它只是从我的Dogs类中获取。

我可以轻松地在我的 dos 类中构建一个方法,该方法将使用 .toLowerCase 和 .contains 返回一个列表,该方法接受一些文本用于构建包含已过滤项目的新列表,但是当我失败时,我也在这里旋转了一堆通过消费者将其绑定回我的dogData。

这是应用程序、移动应用程序、网络等中的常见任务,因此我必须相信有一种干净/优雅/正确(比其他方式更多)的方法来完成此任务。我想,只是迷失在细节中。

任何帮助将不胜感激。 谢谢你, 鲍勃


您可以复制粘贴运行下面的完整代码
这个想法就像 Todo 应用程序有 3 种不同的UnmodifiableListView

UnmodifiableListView<Task> get allTasks, 
UnmodifiableListView<Task> get incompleteTasks
UnmodifiableListView<Task> get completedTasks

托多的例子https://dev.to/shakib609/create-a-todos-app-with-flutter-and-provider-jdh

您可以使用以下代码片段返回UnmodifiableListView您需要基于搜索字符串并在onChanged call provider changeSearchString
所以其他部分就像ListView不必改变

  String _searchString = "";

  UnmodifiableListView<Dog> get dogs => _searchString.isEmpty
      ? UnmodifiableListView(_myDogs)
      : UnmodifiableListView(
          _myDogs.where((dog) => dog.breed.contains(_searchString)));

  void changeSearchString(String searchString) {
    _searchString = searchString;
    print(_searchString);
    notifyListeners();
  }

  ...

  onChanged: (value) {
            Provider.of<Dogs>(context, listen: false)
                .changeSearchString(value);
          },

工作演示通过面包搜索狗

enter image description here

完整代码

import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:collection';
import 'package:provider/provider.dart';

class Dogs extends ChangeNotifier {
  final List<Dog> _myDogs = [
    Dog(name: 'Mackie', age: 8, breed: 'Rottweiler'),
    Dog(name: 'Riley', age: 8, breed: 'Rottweiler'),
    Dog(name: 'Tank', age: 7, breed: 'Mastiff'),
    Dog(name: 'Tanner', age: 7, breed: 'Mastiff'),
    Dog(name: 'Rocky', age: 10, breed: 'Rottweiler'),
    Dog(name: 'Angel', age: 11, breed: 'Poodle'),
    Dog(name: 'Roxie', age: 8, breed: 'St. Bernard'),
    Dog(name: 'Spud', age: 8, breed: 'St. Bernard'),
    Dog(name: 'Nick', age: 4, breed: 'Rottweiler'),
  ];

  String _searchString = "";

  UnmodifiableListView<Dog> get dogs => _searchString.isEmpty
      ? UnmodifiableListView(_myDogs)
      : UnmodifiableListView(
          _myDogs.where((dog) => dog.breed.contains(_searchString)));

  void changeSearchString(String searchString) {
    _searchString = searchString;
    print(_searchString);
    notifyListeners();
  }
}

class Dog {
  final String breed;
  final String name;
  final int age;

  Dog({this.breed, this.name, this.age});
}

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Dogs(),
      child: MyApp(),
    ),
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final _controller = TextEditingController();
  String _searchText;

  @override
  void initState() {
    _controller.addListener(
      () {
        setState(() {
          _searchText = _controller.text;
        });
      },
    );
    super.initState();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Dogs',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Dogs'),
        ),
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            TextField(
              controller: _controller,
              decoration: InputDecoration(
                hintText: "Search",
                prefixIcon: Icon(Icons.search),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.all(
                    Radius.circular(4.0),
                  ),
                ),
              ),
              onChanged: (value) {
                Provider.of<Dogs>(context, listen: false)
                    .changeSearchString(value);
              },
            ),
            Consumer<Dogs>(builder: (context, dogData, child) {
              print(dogData.dogs.toString());
              return Expanded(
                child: ListView.builder(
                    shrinkWrap: true,
                    itemCount: dogData.dogs.length,
                    itemBuilder: (context, index) => Card(
                          elevation: 3,
                          child: ListTile(
                            title: Text(dogData.dogs[index].name),
                          ),
                        )),
              );
            }),
          ],
        ),
      ),
    );
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Provider 和模型类搜索/过滤 ListView 的相关文章

随机推荐

  • 交换链表的相邻元素

    下面是我的代码 用于递归交换链表的相邻元素 交换后我失去了指向每个第二个元素的指针 输入是 1 gt 2 gt 3 gt 4 gt 5 gt 6 gt 7 我期望输出 2 gt 1 gt 4 gt 3 gt 6 gt 5 gt 7 但我的输
  • 如何在 Flutter 中保持每 5 秒更换一张图像?

    状态变量 var moviePhotos http www kiwithebeauty com wp content uploads 2017 11 BLACK PANTHER COLLAGE KIWI THE BEAUTY MOVIE M
  • 导入 google play 服务后 Cordova 构建问题

    在admob SDK新更新后 现在我们需要将google play服务项目导入到我们的项目中 以在我们的应用程序中获利并展示广告 我正在使用 Apache Cordova Phonegap 创建一个应用程序 并用它创建了 android 项
  • 为什么同一层上的文本会重叠 - 即使它具有不透明的背景?

    我知道我可以通过使用相对 绝对定位创建新的堆叠上下文来将元素堆叠在单独的层中 Demo 或不透明度 Demo 然而 我的印象是 默认情况下 html 中更靠下的元素将绘制在前面的元素之上 显然 元素的背景是如此 但我只是注意到文本的工作方式
  • 执行脚本IntrinsicYuvToRgb

    我想将Yuv中的byte 转换为Rgb中的byte ScriptIntrinsic ScriptIntrinsicYuvToRgb 应该执行此操作 基于此example 这是我现在拥有的一些代码 byte imageData gathery
  • 仅当选择 ListViewItem 时显示内容

    我有一个ListBox当其中之一ListBoxItems被选中我想更改按钮 查看 的可见性并显示它 这意味着默认状态是隐藏 这是否可能 如果可以 我是否使用 XAML 中的触发器或后面的代码来解决此问题 XAML 片段
  • 如何检查文件锁定? [复制]

    这个问题在这里已经有答案了 有没有办法在不使用 try catch 块的情况下检查文件是否被锁定 现在 我知道的唯一方法就是打开文件并捕获任何System IO IOException 当我遇到类似的问题时 我完成了以下代码 public
  • “while”和“for”循环的范围是什么?

    a的范围是什么while and for loop 例如 如果我在循环中声明了一个对象 它的行为是什么以及为什么 在以下示例中 循环的每次迭代都会销毁并重新创建所有变量 除了i 它在循环迭代之间持续存在 并且可用于 for 循环中的条件表达
  • Unity 5执行一段代码后无响应

    我绝对是 Unity 的初学者 我一直在开发一个用户界面 它是一个简单的登录表单 其中我有两个Toggle用于选择性别 即男性或女性 我一直在做的是调用一个方法来检查是否已经选择了男性 当按下另一个开关时 它将删除男性的检查 My Unit
  • 有什么方法可以使 {% extends '...' %} 有条件吗? - 姜戈

    我想在 AJAX 和常规 HTTP 调用之间共享一个模板 唯一的区别是一个模板需要与base htmlhtml 另一个没有 任何想法 其他答案要求您传递额外的上下文变量 但只要可以访问请求对象 就没有必要 extends request i
  • 从左到右显示 ImageView 的动画[重复]

    这个问题在这里已经有答案了 可能的重复 动画 ImageView 宽度而不缩放 我想做的是创建一个动画 其中 ImageView 从左到右显示 剪辑动画 图像不应缩放 我尝试更改scaleType 然后将ScaleAnimation直接应用
  • 堆叠条形图,每个堆叠独立的填充顺序

    我面临着一种行为ggplot2 排序和堆积条形图我无法理解 我读过一些关于它的问题 here here等等 但不幸的是我找不到适合我的解决方案 也许答案很简单 但我看不到 希望这不是一个骗子 我的主要目标是根据排序列 此处称为orderin
  • java数学计算给定半径1.00的圆的坐标

    在我的一项作业中 我被要求编写一个程序来计算半径为 1 0 的圆上的点的 x y 坐标 以 0 1 为增量显示范围从 1 00 到负 1 00 的所有 x 值的 y 值输出 并使用以下命令整齐地显示输出printf 其中所有 x 值都垂直对
  • 如何直接进入函数而不进入参数的中间函数?

    在 Visual Studio 2013 或任何版本 中 我正在调试 C 项目 我希望能够绕过单步执行由于参数传递到感兴趣的函数而被调用的中间函数 我怎样才能绕过进入这些中间函数 不直接感兴趣 并直接进入我感兴趣的函数 例如 假设我有一个函
  • 如何在freemarker中自定义数字格式?

    我正在使用 freemarker 并尝试以这种格式显示数字 3 343 434 00例如 这很容易通过使用来解决 total string currency 假设 总数 是某个数字 但是 当我有负数时 它会像这样显示 343 34 而不是这
  • 比较 R 中的 svd 和 princomp

    我想要得到singular values of a matrix in R获取主成分 然后也使用 princomp x 来比较结果 我知道 princomp 会给出主要成分 Question 如何从 d u 和 v 中获取主成分 解决方案s
  • 使用Python组合所有视频的特征

    假设我有 20 个视频 它们具有相同的场景 尺寸和来自同一台相机 让我们假设这二十个视频中的一个有一个人走过 所有其他视频大多相同 除了微小的自然变化 例如风吹树叶等 我正在寻找一种将所有 20 个视频合并为 1 个视频的好方法 我所说的合
  • 尝试加载使用存储传递的数据

    我正在尝试获取正在传递的数据并将其加载到各种文本字段中 现在 我有一个 html 文件 其中包含以下内容 然后 我有一个 js 文件 其中包含我的整个布局以及所有文本字段等以及我的整个商店 到目前为止 我的商店尝试加载数据 但我不确定尝试从
  • 如何启动 ajax 推送网站(activemq 或 cometd 或其他)?

    我想启动一个使用 ajax 推送的应用程序 但是应该正确配置 Web 服务器 并且我不知道如何在服务器端组件上启动 我想从道场彗星然后读了一些博客说activeMQ是较旧的 也是 ajax 推送方面的旗舰载体 但也有另一个博客说它很难设置并
  • 使用 Provider 和模型类搜索/过滤 ListView

    我想通过在搜索字段中输入的文本来过滤列表视图 在线和本网站上有很多示例 但所有内容都过于简化 所有内容都在一个有状态的小部件中 和 或看起来有点混乱 可能不是构建事物的最佳方式 我有一个简单的应用程序 它使用 Provider 一个模型类