Flutter学习-26- 微信项目学习-搜索框实现搜索
- 上一篇我们实现了自定义搜索框,我们实现搜索框的内容实现搜素的效果
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
的方式赋值刷新页面
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(() {});
}
结果
3. 显示选中字体
想要实现我们输入的字显示选中
的颜色,我们要自定义标题使用富文本
展示
这里我们修改下接口改为英文名字
我们根据这个传入的字符串截取split
Widget _titleName(String name){
List<TextSpan> spans = [];
List<String> strs = name.split(_searchStr);
print('$name:$strs');
return RichText(text: TextSpan(children: spans));
}
打印结果
字符串根据我们选中的进行分割
,其中数组中空字符串
代表了我们输入的搜素内容
,我们可以根据这个判断
但是还是有些问题,比如我们搜素ss
,打印结果
Jessica Rodriguez:[Je, ica Rodriguez],
我们判断数组下标不是最后一个
的话,每次添加他们之间的间隔
,因为字符串时以这个搜索内容区分的,没在数组中展示
,但是有间隔
就表示我们之间有输入内容
。
我们判断当前i不是最后一个
就加入我们的搜索内容
我们还有一个问题,当最后一个是我们检索的内容的话,它是‘’
但是我们在他前面又添加了
,有问题会。
因此我们在判断空字符串的时候还要加个判断,空字符串不是最后一个
。
最终代码我们替换之前的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 感兴趣的可以看看。
转载自:https://juejin.cn/post/7034073463736238093