flutter的调试前端开发那些事儿Flutter

Flutter收藏库——简单的搜索功能

2020-05-22  本文已影响0人  _破晓之翼

最近在做项目时需要用到搜索框搜索功能,百度后记之以温习。

实现搜索功能的SearchDelegate

实现搜索功能的原理简单来说,就是在点击搜索框时调用了showSearch(context: context,
delegate: SearchBarDelegate())方法跳转到搜索界面。


在SearchDelegate<T>中定义了如下几个方法,我们使用时可将它重写:

class SearchBarDelegate extends SearchDelegate<String> {

  //返回值为我们搜索框右侧的一个控件
  @override
  List<Widget> buildActions(BuildContext context) {
    return null;
  }

  //返回值为我们搜索框左侧的一个控件
  @override
  Widget buildLeading(BuildContext context) {
    return null;
  }

  //返回值为我们搜到内容后的展现
  @override
  Widget buildResults(BuildContext context) {
    return null;
  }

  //设置推荐
  @override
  Widget buildSuggestions(BuildContext context) {
    return null;
  }

  //返回一个主题,也就是可以自定义搜索界面的主题样式
  @override
  ThemeData appBarTheme(BuildContext context) {
    // TODO: implement appBarTheme
    return super.appBarTheme(context);
  }
}

Demo演示

这是搜索框所在的界面:


搜索框所在的界面

自定义搜索框代码如下:

Scaffold(
      appBar: AppBar(
        title: Padding(
            padding: EdgeInsets.only(top: 2,bottom: 2,left: 16),
          child: Container(
            height: 35,
            width:  MediaQuery.of(context).size.width-64,
            decoration: BoxDecoration(
                color: Color.fromRGBO(230,230,230,1.0),
                borderRadius: BorderRadius.circular(20)
            ),
            child: InkWell(
              child: Row(
                children: <Widget>[
                  Padding(padding: EdgeInsets.only(left: 10,right: 10),
                      child: Icon(Icons.search,color: Colors.teal)),
                  Text("点我进行搜索",style: TextStyle(color: Colors.grey,fontSize: 15),)
                ],
              ),
              onTap: (){
                //这里是跳转搜索界面的关键
                showSearch(context: context,delegate: SearchBarDelegate());
              },
            ),
          ),
        )
      ),
    );

点击搜索框后会执行showSearch(context: context,delegate: SearchBarDelegate());跳转到搜索界面。

一般数据都是从后端来,这里没有后端我就用简单的几个蔬菜做为例子。

var nameList = [
    "绿皮南瓜","番茄", "白菜", "胡萝卜","土豆","甜菜","白甜"
  ];
bool flag;//判断搜索框内输入的内容是否存在于数据列表里
搜索界面
重写buildActions方法(搜索框右侧的一个控件):

这里我设置了一个叉按钮,用于清空搜索框里面的内容。

@override
  List<Widget> buildActions(BuildContext context) {
    return [
      IconButton(
        icon: Icon(Icons.clear),
        onPressed: () {
          query = "";
          showSuggestions(context);
        }, //搜索值为空
      )
    ];
  }
重写buildLeading方法(搜索框左侧的一个控件):

这里我在网上趴了个带动画的返回按钮,返回至上一个页面。

@override
  Widget buildLeading(BuildContext context) {
    return IconButton(
        icon: AnimatedIcon(
            icon: AnimatedIcons.menu_arrow, progress: transitionAnimation
        ),
        onPressed: () => close(context, null)  //点击时关闭整个搜索页面
    );
  }
重新buildResults方法(搜到内容后的展现):

(注:query为我们在搜索框内输入的内容)
这里先判断了我们输入的数据是否存在于数据列表里,如果存在那么将展示搜索出来的结果,如果不存在则展示没有找到。

@override
  Widget buildResults(BuildContext context) {
    for(int i=0;i<nameList.length;i++){
      if(query==nameList[i]){
        flag = true;
        break;
      }
      else{
        flag = false;
      }
    }

    return flag == true ? Padding(
        padding: EdgeInsets.all(16),
        child: InkWell(
          child: Text(query),
          onTap: (){
            Navigator.push(
              context,
              new MaterialPageRoute(
                builder: (context) => new TextScreen(s: query),
                //TextScreen()用于展示我们想要通过搜索到达的页面,
                //这里用到了构造函数传值。
              ),
            );
          },
        ))
        :
        Center(
          child: Text("没有找到这个蔬菜!!!"),
        );
  }
重写buildSuggestions方法(设置推荐):

(注:这里的suggestionsList和recentSuggest我把他们设置成了和nameList一样的内容)
在这里的RichText用于显示不同的样式的文字,当我们输入首个关键字时,它会补全我们输入的内容。

@override
  Widget buildSuggestions(BuildContext context) {
    final suggestionsList= query.isEmpty ? recentSuggest
        :
    searchList.where((input)=> input.startsWith(query)).toList();
//判断集合中的字符串是否以搜索框内输入的字符串开头,
//是则返回true,并将筛选出来的结果以list的方式储存在searchList里
    return ListView.builder(
        itemCount:suggestionsList.length,
        itemBuilder: (context,index) {
          return InkWell(
            child: 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)
                      )
                    ]
                ),
              ),
            ),
            onTap: (){
              Navigator.push(
                context,
                new MaterialPageRoute(
                  builder: (context) => new TextScreen(s: suggestionsList[index]),
                ),
              );
            },
          );
      }
    );
}
我们想要通过搜索到达的页面:
class TextScreen extends StatelessWidget {

  final String s;
  TextScreen({Key key, @required this.s}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    // Use the Todo to create our UI
    return new Scaffold(
      appBar:  AppBar(
        title: Text("搜索结果内容"),
      ),
      body: Padding(
        padding: EdgeInsets.all(16.0),
        child: Center(
          child: Text(s),
        )
      ),
    );
  }
}

最后的成品展示:

搜索功能demo.gif

OVER~
在这里https://www.jianshu.com/p/63aca25a463c学习了

上一篇 下一篇

猜你喜欢

热点阅读