【问题标题】:How to use SearchDelegate to show recent search history in flutter?如何使用 SearchDelegate 在 Flutter 中显示最近的搜索历史?
【发布时间】:2020-05-08 16:18:12
【问题描述】:

我想使用showSearch 从用户那里获取搜索文本(或查询)。我还想将最近的搜索显示为建议,并根据输入的文本过滤搜索历史。

那么我该如何实现呢?

【问题讨论】:

    标签: flutter dart search


    【解决方案1】:

    custom_search_delgates.dart

    import 'package:flutter/material.dart';
    
    typedef OnSearchChanged = Future<List<String>> Function(String);
    
    class SearchWithSuggestionDelegate extends SearchDelegate<String> {
      ///[onSearchChanged] gets the [query] as an argument. Then this callback
      ///should process [query] then return an [List<String>] as suggestions.
      ///Since its returns a [Future] you get suggestions from server too.
      final OnSearchChanged onSearchChanged;
    
      ///This [_oldFilters] used to store the previous suggestions. While waiting
      ///for [onSearchChanged] to completed, [_oldFilters] are displayed.
      List<String> _oldFilters = const [];
    
      SearchWithSuggestionDelegate({String searchFieldLabel, this.onSearchChanged})
          : super(searchFieldLabel: searchFieldLabel);
    
      ///
      @override
      Widget buildLeading(BuildContext context) {
        return IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () => Navigator.pop(context),
        );
      }
    
      @override
      List<Widget> buildActions(BuildContext context) {
        return [
          IconButton(
            icon: Icon(Icons.clear),
            onPressed: () => query = "",
          ),
        ];
      }
    
      ///OnSubmit in the keyboard, returns the [query]
      @override
      void showResults(BuildContext context) {
        close(context, query);
      }
    
      ///Since [showResults] is overridden we can don't have to build the results.
      @override
      Widget buildResults(BuildContext context) => null;
    
      @override
      Widget buildSuggestions(BuildContext context) {
        return FutureBuilder<List<String>>(
          future: onSearchChanged != null ? onSearchChanged(query) : null,
          builder: (context, snapshot) {
            if (snapshot.hasData) _oldFilters = snapshot.data;
            return ListView.builder(
              itemCount: _oldFilters.length,
              itemBuilder: (context, index) {
                return ListTile(
                  leading: Icon(Icons.restore),
                  title: Text("${_oldFilters[index]}"),
                  onTap: () => close(context, _oldFilters[index]),
                );
              },
            );
          },
        );
      }
    }
    

    用法:

    import 'package:flutter/material.dart';
    import 'package:flutter_app/custom_search_delgates.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    void main() {
      runApp(MaterialApp(home: Home()));
    }
    
    class Home extends StatefulWidget {
      @override
      _HomeState createState() => _HomeState();
    }
    
    class _HomeState extends State<Home> {
      Future<void> _showSearch() async {
        final searchText = await showSearch<String>(
          context: context,
          delegate: SearchWithSuggestionDelegate(
            onSearchChanged: _getRecentSearchesLike,
          ),
        );
    
        //Save the searchText to SharedPref so that next time you can use them as recent searches.
        await _saveToRecentSearches(searchText);
    
        //Do something with searchText. Note: This is not a result.
      }
    
      Future<List<String>> _getRecentSearchesLike(String query) async {
        final pref = await SharedPreferences.getInstance();
        final allSearches = pref.getStringList("recentSearches");
        return allSearches.where((search) => search.startsWith(query)).toList();
      }
    
      Future<void> _saveToRecentSearches(String searchText) async {
        if (searchText == null) return; //Should not be null
        final pref = await SharedPreferences.getInstance();
    
        //Use `Set` to avoid duplication of recentSearches
        Set<String> allSearches =
            pref.getStringList("recentSearches")?.toSet() ?? {};
    
        //Place it at first in the set
        allSearches = {searchText, ...allSearches};
        pref.setStringList("recentSearches", allSearches.toList());
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text("Search Demo"),
            actions: <Widget>[
              IconButton(
                icon: Icon(Icons.search),
                onPressed: _showSearch,
              ),
            ],
          ),
        );
      }
    }
    

    【讨论】:

    • 请编辑问题以获得这些详细信息,而不是作为答案发布。
    • @Zoinks:OP answered their own question 在这里。
    • 一开始看起来不像,谢谢提到Martijn!
    • @Jaques 我回答了我自己的问题。
    • 那就这样说吧,因为目前看来您发布了其他信息
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-26
    • 2019-06-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 2015-01-06
    相关资源
    最近更新 更多