如何使用搜索委托在颤振中显示最近的搜索历史?



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

那么我该如何实现这一目标呢?

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,
),
],
),
);
}
}
import 'package:flutter/material.dart';
class Searching extends SearchDelegate {
@override
Widget? buildLeading(BuildContext context) {
return IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => close(context, null),
);
}
@override
List<Widget>? buildActions(BuildContext context) {
return [
IconButton(
icon: const Icon(Icons.clear),
// color: Colors.grey[800],
onPressed: () {
if (query.isEmpty) {
close(context, null);
} else {
query = '';
}
},
),
];
}
@override
Widget buildResults(BuildContext context) => SearchResult(query: query);

// search history
@override
Widget buildSuggestions(BuildContext context) {
List suggestions = localUser.searches!.where((search) {
return search.toLowerCase().contains(query.toLowerCase());
}).toList();
return ListView.builder(
itemCount: suggestions.length,
itemBuilder: (context, index) {
final suggestion = suggestions[index];
return ListTile(
leading: Icon(Icons.history, size: 22),
title: Text(suggestion, style: TextStyle(fontSize: 16)),
onTap: () {
query = suggestion;
showResults(context);
},
trailing: IconButton(
icon: Icon(Icons.close),
iconSize: 15,
onPressed: () {
localUser.removeSearched(suggestion);
UserPreferences.setUser(localUser);
buildSuggestions(context);
},
),
);
},
);
}
}

最新更新