代码之家  ›  专栏  ›  技术社区  ›  Rushikumar Jeremy French

颤振:在列表中搜索

  •  0
  • Rushikumar Jeremy French  · 技术社区  · 6 年前

    在学习颤振框架/Dart的过程中,我创建了一个示例项目。

    我有一门课叫 person.dart 包括以下内容:

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

    接下来,我有一个“建设者”课程, person_builder.dart ,其中我创建了人员的样本数据:

    “导入”软件包:adv_search/model/person。飞镖;

    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"
          ),
    
        ];
      }
    }
    

    我已经在顶部导航栏添加了搜索功能。。。单击搜索图标后,搜索字段打开(在顶部导航内),允许我提供搜索输入。我有一个控制器,它有一个监听器,可以很好地捕获用户输入,如我的 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。建设者 (第106行)--

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

    我得到的错误是:

    NoSuchMethodError:类“Person”没有实例方法“contains”

    接收者:“Person”的实例

    尝试呼叫:contains(“约翰”)

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

    1. 我怎样才能允许用户根据名字或姓氏进行搜索,并根据用户输入,使用筛选出的人的卡片刷新视图?
    2. 当我点击 搜索 图标,输入字段不是自动聚焦的。。。我的搜索功能设置正确吗?
    3. 是否有更好的/推荐的方法来创建数据(人员列表)?

    编辑1

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

    编辑2

    补充 全部的 完整的代码文件;重新措辞了帖子的部分内容,并添加了几个附加问题。

    0 回复  |  直到 5 年前
        1
  •  4
  •   Sukhi    6 年前

    错误是准确地告诉您代码的错误。当你写作的时候 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);  
       }
    }
    

    然后在列表视图中显示_searchList而不是full 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()
        );
      }
    

    最后,设置基于用户交互的搜索。

        2
  •  2
  •   Rushikumar Jeremy French    6 年前

    所以这不是小事。。。很可能是因为我不熟悉飞镖/颤振框架。。。无论如何,这个答案建立在@Sukhi的回答之上:

    首先是 getPeople 方法亲自创建。dart需要返回类型 List<Person>

    最后,在 main.dart 文件中,发生了以下更改:

    1. 在…内 _ListPersonPageState State ,我们需要定义两个不同的列表(如@Sukhi所述): List<Person> _personList = [] List<Person> _filteredList = []

    2. 里面 initState 方法:

      a、 我们需要创建一个临时列表,遍历从 找人 调查方法 PeopleDataBuilder 类,并将返回列表中的每个项添加到我们创建的临时列表中

      b、 然后,我们 setState 在它里面,我们把这个临时列表分配给 _personList 然后分配 _个人主义者 _filteredList

      c、 当我们添加一个 听众 对于控制器,我们进行一些(健全性)验证,并在此基础上 设定状态

    3. 里面 build 方法,我们需要(再次)创建一个临时列表(如果 filter 不为空),然后分配 临时名单 _过滤列表

    4. 有一些怪癖。。。例如当点击搜索图标时光标不出现,等等。。。因此,基本属性被添加/定义为 TextField (例如:。 cursorColor: Colors.white, (等等)

    注: 创建这些临时列表很重要。。。否则在使用搜索时会出现错误(我认为错误是 迭代过程中的并发修改 ,如果我没弄错的话)

    满的 主要的飞奔 代码,供参考:

    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<Person> _personList = [];
      List<Person> _filteredList = [];
      TextEditingController controller = new TextEditingController();
      String filter = "";
    
      Widget appBarTitle = new Text("List of People");
      Icon actionIcon = new Icon(Icons.search);
    
      @override
      void dispose() {
        controller.dispose();
        super.dispose();
      }
    
      @override
      void initState() {
        PersonDataBuilder pdb = new PersonDataBuilder();
        List<Person> tmpList = new List<Person>();
        for(int i=0; i < pdb.getPeople().length; i++) {
          tmpList.add(pdb.getPeople()[i]);
        }
        setState(() {
          _personList = tmpList;
          _filteredList = _personList;
        });
        controller.addListener(() {
          if(controller.text.isEmpty) {
            setState(() {
              filter = "";
              _filteredList = _personList;
            });
          } else {
            setState(() {
              filter = controller.text;
            });
          }
        });
        super.initState();
      }
    
      @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(
                      controller: controller,
                      decoration: new InputDecoration(
                        prefixIcon: new Icon(Icons.search, color: Colors.white),
                        hintText: "Search...",
                        hintStyle: new TextStyle(color: Colors.white),
                      ),
                      style: new TextStyle(
                        color: Colors.white,
                      ),
                      autofocus: true,
                      cursorColor: Colors.white,
                    );
                  } else {
                    this.actionIcon = new Icon(Icons.search);
                    this.appBarTitle = new Text("List of People");
                    _filteredList = _personList;
                    controller.clear();
                  }
                });
              },
            ),
          ],
        );
    
        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),
          ),
        );
    
        if((filter.isNotEmpty)) {
          List<Person> tmpList = new List<Person>();
          for(int i = 0; i < _filteredList.length; i++) {
            if(_filteredList[i].personFirstName.toLowerCase().contains(filter.toLowerCase())) {
              tmpList.add(_filteredList[i]);
            }
          }
          _filteredList = tmpList;
        }
    
        final appBody = Container(
          child: ListView.builder(
            scrollDirection: Axis.vertical,
            shrinkWrap: true,
            itemCount: _personList == null ? 0 : _filteredList.length,
            itemBuilder: (BuildContext context, int index) {
              return personCard(_filteredList[index]);
            },
          ),
        );
    
        return Scaffold(
          appBar: appTopAppBar,
          body: appBody,
        );
      }
    }