Flutter:搜索列表

标签 flutter dart

在学习Flutter framework/Dart的过程中,我创建了一个示例工程。

我有一个名为 person.dart 的类,其内容如下:

class Person {
  String personFirstName;
  String personLastName;

  Person(
    {this.personFirstName, this.personLastName}
  );
}

接下来,我有一个“构建器”类,person_builder.dart,我在其中创建人员样本数据:

导入 'package:adv_search/model/person.dart';

class PersonDataBuilder {
  List getPeople() {
    return [
      Person(
          personFirstName: "John",
          personLastName: "Smith"
      ),
      Person(
          personFirstName: "Alex",
          personLastName: "Johnson"
      ),
      Person(
          personFirstName: "Jane",
          personLastName: "Doe"
      ),
      Person(
          personFirstName: "Eric",
          personLastName: "Johnson"
      ),
      Person(
          personFirstName: "Michael",
          personLastName: "Eastwood"
      ),
      Person(
          personFirstName: "Benjamin",
          personLastName: "Woods"
      ),
      Person(
          personFirstName: "Abraham",
          personLastName: "Atwood"
      ),
      Person(
          personFirstName: "Anna",
          personLastName: "Clack"
      ),
      Person(
          personFirstName: "Clark",
          personLastName: "Phonye"
      ),
      Person(
          personFirstName: "Kerry",
          personLastName: "Mirk"
      ),
      Person(
          personFirstName: "Eliza",
          personLastName: "Wu"
      ),
      Person(
          personFirstName: "Jackey",
          personLastName: "Lee"
      ),
      Person(
          personFirstName: "Kristin",
          personLastName: "Munson"
      ),
      Person(
          personFirstName: "Oliver",
          personLastName: "Watson"
      ),

    ];
  }
}

我已将搜索功能添加到顶部导航栏,效果很好...单击搜索图标后,搜索字段(在顶部导航栏内)打开,允许我提供搜索输入。我有一个带有监听器的 Controller ,可以很好地捕获用户输入,如我的 main.dart 文件所示:

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:adv_search/model/person.dart';
import 'package:adv_search/data/person_builder.dart';

void main() => runApp(new AdvancedSearch());

class AdvancedSearch extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'List of People',
      home: new ListPersonPage(title: 'List of People'),
    );
  }
}

class ListPersonPage extends StatefulWidget {
  ListPersonPage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _ListPersonPageState createState() => _ListPersonPageState();
}

class _ListPersonPageState extends State<ListPersonPage> {
  List people;
  TextEditingController controller = new TextEditingController();
  String filter;

  Widget appBarTitle = new Text("List of People");
  Icon actionIcon = new Icon(Icons.search);

  @override
  void initState() {
    PersonDataBuilder pdb = new PersonDataBuilder();
    people = pdb.getPeople();
    controller.addListener(() {
      setState(() {
        filter = controller.text;
      });
    });
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    final appTopAppBar = AppBar(
      elevation: 0.1,
      title: appBarTitle,
      actions: <Widget>[
        new IconButton(
          icon: actionIcon,
          onPressed: () {

            setState(() {
              if (this.actionIcon.icon == Icons.search) {
                this.actionIcon = new Icon(Icons.close);
                this.appBarTitle = new TextField(
                  style: new TextStyle(
                    color: Colors.white,
                  ),
                  decoration: new InputDecoration(
                      prefixIcon: new Icon(Icons.search, color: Colors.white),
                      hintText: "Search...",
                      hintStyle: new TextStyle(color: Colors.white)),
                  controller: controller,
                );
              } else {
                this.actionIcon = new Icon(Icons.search);
                this.appBarTitle = new Text("List of People");
              }
            });

          },
        ),
      ],
    );

    ListTile personListTile(Person person) => ListTile(
      title: Text(
        person.personFirstName + " " + person.personLastName,
        style: TextStyle(color: Colors.black45, fontWeight: FontWeight.bold),
      ),);

    Card personCard(Person person) => Card(
      child: Container(
        decoration: BoxDecoration(color: Colors.grey[300]),
        child: personListTile(person),
      ),
    );

    final appBody = Container(
      child: ListView.builder(
        scrollDirection: Axis.vertical,
        shrinkWrap: true,
        itemCount: people.length,
        itemBuilder: (BuildContext context, int index) {
          //return filter == null || filter == "" ? personCard(people[index]) : people[index].contains(filter) ? personCard(people[index]) : new Container();
          return filter == null || filter == "" ? personCard(people[index]) : new Container();
        },
      ),
    );

    return Scaffold(
      appBar: appTopAppBar,
      body: appBody,
    );
  }
}

但是,我遇到困难并寻求指导的地方是 ListView.builder

这就是我目前在 ListView.builder(第 106 行)中返回的内容--

return filter == null || filter == "" ? personCard(people[index]) : people[index].contains(filter) ? personCard(people[index]) : new Container();

我得到的错误是:

NoSuchMethodError: Class 'Person' has no instance method 'contains'

Receiver: Instance of 'Person'

Tried calling: contains("John")

目前,鉴于上述错误,我根本无法过滤。我想知道:

  1. 如何允许用户按名字或姓氏进行搜索,并根据用户输入使用已过滤的人员卡片刷新 View ?
  2. 当我单击搜索 图标时,输入字段没有自动聚焦...我设置搜索功能的方式是否正确?
  3. 是否有更好/推荐的方法来创建数据(人员列表)?

编辑 1

我应该补充一点:启动应用程序后,我可以看到通过构建器类创建的所有人员的列表。

编辑 2

完整添加了ALL代码文件;重新措辞了帖子的部分内容并添加了几个额外的问题。

最佳答案

该错误准确地告诉您您的代码出了什么问题。当您编写 items[index].contains(searchFilter) 时,编译器会尝试在 Person 类中查找“contains”方法。由于您尚未实现它,因此它会引发异常。

实现搜索的一种方法如下:

List<Person> _personList = [] ;
List<Person> _searchList = [] ;

// populate _personList

_personList.forEach((p) {
   if (p.personFirstName == searchFilter or p.personLastName == searchFilter) {
       _searchList.add(f);  
   }
}

然后您在 ListView 中显示 _searchList 而不是完整的 _personList。例如,如下所示:

    Widget _buildPersonListView() {
      if (!_isSearching) {
         return _listContents(_personList);
      } else {
         return _listContents(_searchList);
      }

然后你定义 _listContents 如下:

Widget _listContents(List<Person> list) {
    // implement list view
}

将您的小部件构建方法设置为:

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      .....
      appBar: buildBar(context),
      body: _buildPersonView()
    );
  }

最后,根据用户交互设置_isSearching。

关于Flutter:搜索列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57469751/

相关文章:

android - Navigator.push() 永远循环

flutter - 'Wrap' 小部件 - 项目对齐

flutter - 我们如何从 Windows 应用程序商店中发布 Flutter 应用程序

unit-testing - 使用 PageObjects 测试具有嵌套在内部的复杂角度组件的组件

flutter - 断言失败 : line 5070 pos 12: '<optimized out>' : is not true

flutter - 在 flutter 中验证登录后屏幕未加载

dart - 如何在 pub 包中正确使用 dart ffi?

dart - 如何为 Flutter 应用绘制折线图?

android - 聚焦 ListView 的底部? flutter

flutter - 如何为 Dart/Flutter 包设置镜像/公司范围的缓存?