Flutter 实现简单搜索功能
先建立一个主文件,继承StatelessWidget
,然后在home属性中加入SearchBarDemo
,这是一个自定义的Widget,主要代码都在这个文件中。
import 'package:flutter/material.dart'; import 'search_bar_demo.dart'; void main() =>runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title:'Flutter Demo', theme: ThemeData.light(), home: SearchBarDemo() ); } }
然后是搜索页面,里面包含数据及搜索功能。
工作中这些数据是后台传递给我们,或者写成配置文件的,这里我们就以List的方式代替了。我们在这个文件中定义了两个List:
const searchList = [ 'jiejie-大长腿', 'jiejie-水蛇腰', 'gege-帅气欧巴', 'gege-小鲜肉' ]; const recentSuggest = [ '推荐-1', '推荐-2', ];
点击搜索按钮
class SearchBarDemo extends StatefulWidget { _SearchBarDemoState createState() => _SearchBarDemoState(); } class _SearchBarDemoState extends State<SearchBarDemo> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('SearchBarDemo'), actions: <Widget>[ IconButton( icon: Icon(Icons.search), onPressed: (){ showSearch(context: context,delegate: SearchBarDelegate()); }, ) ], ), ); } }
在点击图标时执行SearchBarDelegate
类,这个类继承与SearchDelegate
类,继承后要重写里边的四个方法。
重写buildActions方法:
buildActions
方法时搜索条右侧的按钮执行方法,我们在这里方法里放入一个clear图标。 当点击图片时,清空搜索的内容。
buildLeading 方法重写
这个时搜索栏左侧的图标和功能的编写,这里我们才用AnimatedIcon
,然后在点击时关闭整个搜索页面。
buildResults方法重写
buildResults
方法,是搜到到内容后的展现,因为我们的数据都是模拟的,所以我这里就使用最简单的Container
+Card
组件进行演示了。
buildSuggestions方法重写
这个方法主要的作用就是设置推荐,就是我们输入一个字,然后自动为我们推送相关的搜索结果。
class SearchBarDelegate extends SearchDelegate<String>{ //清空按钮 @override List<Widget>buildActions(BuildContext context){ return [ IconButton( icon: Icon(Icons.clear), onPressed: () => query = "", //搜索值为空 ) ]; } //返回上级按钮 @override Widget buildLeading(BuildContext context) { return IconButton( icon: AnimatedIcon( icon: AnimatedIcons.menu_arrow, progress: transitionAnimation ), onPressed: () => close(context, null) //点击时关闭整个搜索页面 ); } //搜到到内容后的展现 @override Widget buildResults(BuildContext context){ return Container( width: 100.0, height:100.0, child: Card( color:Colors.redAccent, child: Center( child: Text(query), ), ), ); } //设置推荐 @override Widget buildSuggestions(BuildContext context){ final suggestionsList= query.isEmpty ? recentSuggest : searchList.where((input)=> input.startsWith(query)).toList(); return ListView.builder( itemCount:suggestionsList.length, itemBuilder: (context,index) => ListTile( title: RichText( //富文本 text: TextSpan( text: suggestionsList[index].substring(0,query.length), style: TextStyle(color: Colors.black,fontWeight: FontWeight.bold), children: [ TextSpan( text: suggestionsList[index].substring(query.length), style: TextStyle(color: Colors.grey) ) ] ), ), ), ); } }
完整的search_bar_demo.dart文件代码如下:
import 'package:flutter/material.dart'; const searchList = [ 'jiejie-大长腿', 'jiejie-水蛇腰', 'gege-帅气欧巴', 'gege-小鲜肉' ]; const recentSuggest = [ '推荐-1', '推荐-2', ]; class SearchBarDemo extends StatefulWidget { _SearchBarDemoState createState() => _SearchBarDemoState(); } class _SearchBarDemoState extends State<SearchBarDemo> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('SearchBarDemo'), actions: <Widget>[ IconButton( icon: Icon(Icons.search), onPressed: (){ showSearch(context: context,delegate: SearchBarDelegate()); }, ) ], ), ); } } class SearchBarDelegate extends SearchDelegate<String>{ //清空按钮 @override List<Widget>buildActions(BuildContext context){ return [ IconButton( icon: Icon(Icons.clear), onPressed: () => query = "", //搜索值为空 ) ]; } //返回上级按钮 @override Widget buildLeading(BuildContext context) { return IconButton( icon: AnimatedIcon( icon: AnimatedIcons.menu_arrow, progress: transitionAnimation ), onPressed: () => close(context, null) //点击时关闭整个搜索页面 ); } //搜到到内容后的展现 @override Widget buildResults(BuildContext context){ return Container( width: 100.0, height:100.0, child: Card( color:Colors.redAccent, child: Center( child: Text(query), ), ), ); } //设置推荐 @override Widget buildSuggestions(BuildContext context){ final suggestionsList= query.isEmpty ? recentSuggest : searchList.where((input)=> input.startsWith(query)).toList(); return ListView.builder( itemCount:suggestionsList.length, itemBuilder: (context,index) => ListTile( title: RichText( //富文本 text: TextSpan( text: suggestionsList[index].substring(0,query.length), style: TextStyle(color: Colors.black,fontWeight: FontWeight.bold), children: [ TextSpan( text: suggestionsList[index].substring(query.length), style: TextStyle(color: Colors.grey) ) ] ), ), ), ); } }