带有自动完成功能的 Flutter 搜索栏

azr*_*lah 8 search dart flutter

我正在寻找 flutter 文档中的搜索栏,但找不到它,是否有搜索栏小部件在应用栏中具有自动完成功能。例如,我的应用栏上有一个搜索图标。当按下它时会显示搜索框,当您键入它时,它应该会从带有 listtile 的下拉列表中显示自动完成。我设法实现了这一点,但它并不容易使用,因为我需要一个下拉列表来显示建议自动完成,然后如果选择了新路线的建议。

这里的搜索操作

这里是我想要实现的示例图像

小智 3

可以使用Stack来实现自动完成下拉框的效果。下面的示例有 2 个容器 - 都ListView作为子对象保存。一个保存搜索结果,另一个保存一些随机文本作为正文内容。ListView(搜索结果)放置在对齐对象内,并将对齐属性设置为Alignment.topCenter。这可确保 List 出现在顶部,就在AppBar.

更新了评论中提到的帖子(已接受的答案)以获取完整的演示。

如上所述:

    @override
      Widget build(BuildContext context) {
        return new Scaffold(
            key: key,
            appBar: buildBar(context),
            body: new Stack(
              children: <Widget>[
                new Container(
                  height: 300.0,
                  padding: EdgeInsets.all(10.0),
                  child: new DefaultTabController(length: 5, child: mainTabView),
                ),
                displaySearchResults(),
              ],
            ));
      }


      Widget displaySearchResults() {
        if (_IsSearching) {
          return new Align(
              alignment: Alignment.topCenter,
              //heightFactor: 0.0,
              child: searchList());
        } else {
          return new Align(alignment: Alignment.topCenter, child: new Container());
        }
      }
Run Code Online (Sandbox Code Playgroud)

完整演示

class SearchList extends StatefulWidget {
  SearchList({Key key, this.name}) : super(key: key);

  final String name;

  @override
  _SearchListState createState() => new _SearchListState();
}

class _SearchListState extends State<SearchList> {
  Widget appBarTitle = new Text(
    "",
    style: new TextStyle(color: Colors.white),
  );
  Icon actionIcon = new Icon(
    Icons.search,
    color: Colors.white,
  );
  final key = new GlobalKey<ScaffoldState>();
  final TextEditingController _searchQuery = new TextEditingController();
  List<SearchResult> _list;
  bool _IsSearching;
  String _searchText = "";
  String selectedSearchValue = "";

  _SearchListState() {
    _searchQuery.addListener(() {
      if (_searchQuery.text.isEmpty) {
        setState(() {
          _IsSearching = false;
          _searchText = "";
        });
      } else {
        setState(() {
          _IsSearching = true;
          _searchText = _searchQuery.text;
        });
      }
    });
  }

  @override
  void initState() {
    super.initState();
    _IsSearching = false;
    createSearchResultList();
  }

  void createSearchResultList() {
    _list = <SearchResult>[
      new SearchResult(name: 'Google'),
      new SearchResult(name: 'IOS'),
      new SearchResult(name: 'IOS2'),
      new SearchResult(name: 'Android'),
      new SearchResult(name: 'Dart'),
      new SearchResult(name: 'Flutter'),
      new SearchResult(name: 'Python'),
      new SearchResult(name: 'React'),
      new SearchResult(name: 'Xamarin'),
      new SearchResult(name: 'Kotlin'),
      new SearchResult(name: 'Java'),
      new SearchResult(name: 'RxAndroid'),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        key: key,
        appBar: buildBar(context),
        body: new Stack(
          children: <Widget>[
            new Container(
              height: 300.0,
              padding: EdgeInsets.all(10.0),
              child: new Container(
                child: ListView(
                  children: <Widget>[
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                    new Text("Hello World!"),
                  ],
                ),
              ),
            ),
            displaySearchResults(),
          ],
        ));
  }

  Widget displaySearchResults() {
    if (_IsSearching) {
      return new Align(
          alignment: Alignment.topCenter,
          child: searchList());
    } else {
      return new Align(alignment: Alignment.topCenter, child: new Container());
    }
  }

  ListView searchList() {
    List<SearchResult> results = _buildSearchList();
    return ListView.builder(
      itemCount: _buildSearchList().isEmpty == null ? 0 : results.length,
      itemBuilder: (context, int index) {
        return Container(
          decoration: new BoxDecoration(
              color: Colors.grey[100],
            border: new Border(
              bottom: new BorderSide(
                  color: Colors.grey,
                width: 0.5
              )
          )
          ),

          child: ListTile(
            onTap: (){},
            title: Text(results.elementAt(index).name,
                style: new TextStyle(fontSize: 18.0)),
          ),
        );
      },
    );
  }

  List<SearchResult> _buildList() {
    return _list.map((result) => new SearchResult(name: result.name)).toList();
  }

  List<SearchResult> _buildSearchList() {
    if (_searchText.isEmpty) {
      return _list.map((result) => new SearchResult(name: result.name)).toList();
    } else {
      List<SearchResult> _searchList = List();
      for (int i = 0; i < _list.length; i++) {
        SearchResult result = _list.elementAt(i);
        if ((result.name).toLowerCase().contains(_searchText.toLowerCase())) {
          _searchList.add(result);
        }
      }
      return _searchList
          .map((result) => new SearchResult(name: result.name))
          .toList();
    }
  }

  Widget buildBar(BuildContext context) {
    return new AppBar(
      centerTitle: true,
      title: appBarTitle,
      actions: <Widget>[
        new IconButton(
          icon: actionIcon,
          onPressed: () {
            _displayTextField();
          },
        ),

        // new IconButton(icon: new Icon(Icons.more), onPressed: _IsSearching ? _showDialog(context, _buildSearchList()) : _showDialog(context,_buildList()))
      ],
    );
  }

  String selectedPopupRoute = "My Home";
  final List<String> popupRoutes = <String>[
    "My Home",
    "Favorite Room 1",
    "Favorite Room 2"
  ];

  void _displayTextField() {
    setState(() {
      if (this.actionIcon.icon == Icons.search) {
        this.actionIcon = new Icon(
          Icons.close,
          color: Colors.white,
        );
        this.appBarTitle = new TextField(
          autofocus: true,
          controller: _searchQuery,
          style: new TextStyle(
            color: Colors.white,
          ),
        );

        _handleSearchStart();
      } else {
        _handleSearchEnd();
      }
    });
  }

  void _handleSearchStart() {
    setState(() {
      _IsSearching = true;
    });
  }

  void _handleSearchEnd() {
    setState(() {
      this.actionIcon = new Icon(
        Icons.search,
        color: Colors.white,
      );
      this.appBarTitle = new Text(
        "",
        style: new TextStyle(color: Colors.white),
      );
      _IsSearching = false;
      _searchQuery.clear();
    });
  }
}
Run Code Online (Sandbox Code Playgroud)