Flutter学习-26- 微信项目学习-搜索框实现搜索

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

  • 上一篇我们实现了自定义搜索框,我们实现搜索框的内容实现搜素的效果

1. 页面传值

我们要搜索首页数据,所以我们跳转的时候需要把值传递过来。 定义数据,和初始化的方法,选择可选的

class SearchPage extends StatefulWidget {

   final List<ChatModel>? listData;
   SearchPage({this.listData});
    @override
  _SearchPageState createState() => _SearchPageState();
}
复制代码

我们点击searchCell的时候传入,这样我们searchPage就拿到数据了

return GestureDetector(
  onTap: (){

    Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context) => SearchPage(listData: _listData,)));

    print('点击了');
  },
复制代码

2. 实现搜索

我们是把searchBar抽出来放到了一个单独的类,我们可以把数据传进去,根据搜索的内容匹配搜索的结果在在searchPage展示,也可以把searcheBar的值告诉当前页面,之后进行搜索结果展示

2.1 searchBar搜索

class SearchBar extends StatefulWidget {
  final List<ChatModel>? listData;
  final ValueChanged<List<ChatModel>>? searchResult;


  SearchBar({this.listData,this.searchResult});
  @override
  _SearchBarState createState() => _SearchBarState();
}
复制代码

我们定义一个ValueChanged,当发生改变的时候就回调,我们实现这个搜索的方法

//搜索
 searchResult(String searchText){
 if (searchText.isNotEmpty && widget.listData!.isNotEmpty) {
   searResults.clear();
   print('statr');
   print(searchText);
   print(widget.listData!.length);
   for( int i =0;i<widget.listData!.length;i++){
   String name = widget.listData![i].name!;

   if(name.contains(searchText)){
     searResults.add(widget.listData![i]);
   }
 }
   print(searResults);
   widget.searchResult!(searResults);//返回
 }
}
复制代码

我们在搜索框的值发生改变的使用调用

_onChanged(String text){
 searchResult(text);
  setState(() {
    isShowCancleIcon = text.length>0;//当输入框内容大于0的时候显示清除按钮

  });
}
复制代码

我们定义时候监听回调,当发生改变的时候我们就setState的方式赋值刷新页面

image.png

cell我们之前首页的样式

2.2 searchPage实现搜索

我们定义搜索框的回调,把搜索框的搜索内容传递出去

final ValueChanged<String>? onChanged;
SearchBar({this.onChanged});
复制代码

传递出去

if(widget.onChanged != null){
  widget.onChanged!(text);
}
复制代码

在page页接收

SearchBar(listData: widget.listData,
  searchResult:(List<ChatModel> list){
  // print(list);
  //  setState(() {
  //    searResults =list;
  //  });


  },
  onChanged: (String str){
    _searchData(str);
  },
),
复制代码

接受的数据进行处理

List<ChatModel> _modals = [];

void _searchData(String text) {
  _modals.clear(); //每次搜索先清空!
  if (text.length > 0) {
    for (int i = 0; i < widget.listData!.length; i++) {
      //循环检索
      String name = widget.listData![i].name!;
      if (name.contains(text)) {
        _modals.add(widget.listData![i]);
      }
    }
  }
  setState(() {});
}
复制代码

结果 image.png

3. 显示选中字体

想要实现我们输入的字显示选中的颜色,我们要自定义标题使用富文本展示 这里我们修改下接口改为英文名字

image.png

image.png

我们根据这个传入的字符串截取split

Widget _titleName(String name){
  List<TextSpan> spans = [];
  List<String> strs = name.split(_searchStr);
  print('$name:$strs');



  return RichText(text: TextSpan(children: spans));

}
复制代码

image.png 打印结果 image.png

字符串根据我们选中的进行分割,其中数组中空字符串代表了我们输入的搜素内容,我们可以根据这个判断

image.png

但是还是有些问题,比如我们搜素ss,打印结果 Jessica Rodriguez:[Je, ica Rodriguez],

image.png

我们判断数组下标不是最后一个的话,每次添加他们之间的间隔,因为字符串时以这个搜索内容区分的,没在数组中展示,但是有间隔就表示我们之间有输入内容。 我们判断当前i不是最后一个就加入我们的搜索内容

image.png

我们还有一个问题,当最后一个是我们检索的内容的话,它是‘’但是我们在他前面又添加了,有问题会。

image.png

因此我们在判断空字符串的时候还要加个判断,空字符串不是最后一个

image.png

最终代码我们替换之前的Text

Widget _titleName(String name){
  TextStyle _normalStyle =const TextStyle(
    color: Colors.black,
    fontSize: 16
  );

  TextStyle _selectStyle = const TextStyle(
      color: Colors.green,
      fontSize: 16
  );
  List<TextSpan> spans = [];
  List<String> strs = name.split(_searchStr);
  print('$name:$strs');
  for(int i =0 ;i<strs.length;i++){

    String indexStr = strs[i];
    if(indexStr == ''&& i < strs.length - 1){
      spans.add(TextSpan(text: _searchStr,style: _selectStyle));
    }else{
      spans.add(TextSpan(text: indexStr,style: _normalStyle));
      if(i< strs.length -1){
        spans.add(TextSpan(text: _searchStr,style: _selectStyle));

      }
    }

  }
  return RichText(text: TextSpan(children: spans));

}
复制代码

后面会上传下这个demo到github 感兴趣的可以看看。

Guess you like

Origin juejin.im/post/7034073463736238093