Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flutter 颤振:在列表中搜索_Flutter_Dart - Fatal编程技术网

Flutter 颤振:在列表中搜索

Flutter 颤振:在列表中搜索,flutter,dart,Flutter,Dart,在学习颤振框架/Dart的过程中,我创建了一个示例项目 我有一个名为person.dart的类,包含以下内容: class Person { String personFirstName; String personLastName; Person( {this.personFirstName, this.personLastName} ); } 接下来,我有一个“builder”类,person\u builder.dart,我在其中创建了人物的示例数据: 导入“p

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

我有一个名为
person.dart
的类,包含以下内容:

class Person {
  String personFirstName;
  String personLastName;

  Person(
    {this.personFirstName, this.personLastName}
  );
}
接下来,我有一个“builder”类,
person\u 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"
      ),

    ];
  }
}
我已经将搜索功能添加到顶部的导航栏中,很好。。。单击搜索图标后,搜索字段打开(在顶部导航内),允许我提供搜索输入。我有一个具有侦听器的控制器,可以很好地捕获用户输入,如我的
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,
    );
  }
}
我得到的错误是:

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

接收者:“Person”的实例

尝试呼叫:包含(“John”)

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

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

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

    编辑2


    添加了全部代码文件;对文章的部分内容进行了重新措辞,并添加了几个附加问题。

    错误正是告诉您代码的错误所在。编写
    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);  
       }
    }
    
    Widget _listContents(List<Person> list) {
        // implement list view
    }
    
    然后定义_listContents如下:

    List<Person> _personList = [] ;
    List<Person> _searchList = [] ;
    
    // populate _personList
    
    _personList.forEach((p) {
       if (p.personFirstName == searchFilter or p.personLastName == searchFilter) {
           _searchList.add(f);  
       }
    }
    
    Widget _listContents(List<Person> list) {
        // implement list view
    }
    

    最后,set_是基于用户交互的搜索

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

    首先,person\u buider.dart中的
    getPeople
    方法需要返回类型为
    List

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

  • \u ListPersonPageState
    State
    中,我们需要定义两个不同的列表(如@Sukhi所述):
    List\u personList=[]
    List\u filteredList=[]

  • initState
    方法中:

    a。我们需要创建一个临时列表,迭代从PeopleDataBuilder类的
    getPeople
    方法检索的列表,并将返回列表中的每个项添加到我们创建的临时列表中

    b。然后,我们设置状态,在它里面,我们将这个临时列表分配给
    \u personList
    ,然后将这个
    \u personList
    分配给
    \u filteredList

    c。当我们向控制器添加一个侦听器时,我们会进行一些(健全性)验证,并在此基础上,我们
    setState

  • build
    方法中,我们需要(再次)创建一个临时列表(如果
    过滤器不为空),然后将该临时列表分配给
    \u filteredList

  • 有一些怪癖。。。例如单击搜索图标时光标不出现,等等。。。因此,为
    文本字段添加/定义了基本属性(例如
    光标颜色:Colors.white、
    等)

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

    完整的
    main.dart
    code,供参考:

    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,
        );
      }
    }
    
    导入“包装:颤振/材料.省道”;
    进口“包装:颤振/基础.dart”;
    导入“package:adv_search/model/person.dart”;
    导入“package:adv_search/data/person_builder.dart”;
    void main()=>runApp(新的AdvancedSearch());
    类AdvancedSearch扩展了无状态小部件{
    @凌驾
    小部件构建(构建上下文){
    返回新材料PP(
    标题:“人员名单”,
    主页:新建ListPersonPage(标题:“人员列表”),
    );
    }
    }
    类ListPersonPage扩展StatefulWidget{
    ListPersonPage({Key,this.title}):超级(Key:Key);
    最后的字符串标题;
    @凌驾
    _ListPersonPageState createState()=>\u ListPersonPageState();
    }
    类_ListPersonPageState扩展状态{
    列表_personList=[];
    列表_filteredList=[];
    TextEditingController=新的TextEditingController();
    字符串过滤器=”;
    Widget appBarTitle=新文本(“人员列表”);
    图标操作图标=新图标(Icons.search);
    @凌驾
    无效处置(){
    controller.dispose();
    super.dispose();
    }
    @凌驾
    void initState(){
    PersonDataBuilder pdb=新的PersonDataBuilder();
    List tmpList=新列表();
    for(int i=0;iimport '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,
        );
      }
    }