第十二章:wechatDemo(聊天搜索功能)

前言:上节我们简单地封装了网络请求dio,这节我们继续我们的页面完善,本节我们将在聊天页面新增一个搜索栏,用来检索聊天信息

问题抛出:为什么每次进到chatPage的时候,总是会再次请求数据,即每次都会进initState()方法,那么能不能不重新请求呢??????

补充内容

1.为widget持久化保持状态

AutomaticKeepAliveClientMixin:用来保持widget的状态持久

``step1:with AutomaticKeepAliveClientMixin

class _State extends State<ChatPage> with AutomaticKeepAliveClientMixin{
};

step2:重写get wantKeepAlive

  @override
  // TODO: implement wantKeepAlive
  bool get wantKeepAlive => true;

step3:集成父方法

 Widget build(BuildContext context) {
     super.build(context);
    ...
}

...
run:发现还是不能持久化状态!!!!!!

//homePage
return Scaffold(
      body: widgets[_currentIndex],

分析原因:当切换到其他page的时候,widge其实已经不显示了,虽然数据在内存中会存在,但是页面重新出现的时候,会重新进行渲染,所以又会进一次initState(),所以接下来该怎么办呢......

2.重写HomePage,为4个Page保持持久化状态
final _controller = PageController();
return Scaffold(
      body: PageView(
        physics: NeverScrollableScrollPhysics(),//禁止滑动
        controller: _controller,
        children: widgets,
      ),
)
 onTap: (int index){
          _controller.jumpToPage(index);
          setState(() {
            _currentIndex = index;
          });
        },

run:大功告成✿✿ヽ(°▽°)ノ✿

正文:

1.新建搜索栏search_bar.dart
import 'package:flutter/material.dart';
import 'package:wechat_demo/const.dart';

class SearchCell extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      height: 50,
       color: wechatThemeColor,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Container(
            margin: EdgeInsets.only(left: 5,bottom: 5,right: 5),
            decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(5),
              color: Colors.white,
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Image.asset('images/放大镜b.png',width: 20,height: 20,color: Colors.grey,),
              SizedBox(width: 5,),
              Text('搜索',style: TextStyle(color: Colors.grey,fontSize: 16),),
            ],
          )
        ],
      ),
    );
  }
}

引用

Widget _cellForIndex(BuildContext context,int index){
    //返回搜索栏
     if(index == 0){
       return SearchCell();
     }
    index --;//保证从数据源的第0个位置来时取
    return ListTile(
      title: Text(_chatListDatas[index].name),
      leading: Container(
        width: 50,
        height:50,
        child: Image.network(_chatListDatas[index].imageUrl),
      ),
      subtitle: Text(_chatListDatas[index].message,overflow: TextOverflow.ellipsis,),
    );
  }

run

35.png

2.为搜索栏cell添加点击事件,进入搜索页面

新建search_page.dart

import 'package:wechat_demo/chat/search_page.dart';

class SearchCell extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (e){
        Navigator.of(context).push(
          //进入搜索页面
          MaterialPageRoute(builder: (context)=>SearchPage())
        );
      },
      child: Container(
        height: 50,
        color: wechatThemeColor,
        child: ...省略
    );
  }
}
3.搜索页面添加搜索栏SearchBar
class SearchBar extends StatefulWidget {
  @override
  _SearchBarState createState() => _SearchBarState();
}

class _SearchBarState extends State<SearchBar> {
  final TextEditingController _editController =  TextEditingController();
  //显示清除按钮
  bool _showCancle = false;
  //监听文本变化内容
  _onChange(String text){
    if(text.length > 0){
      setState(() {
        _showCancle = true;//显示清除按钮
      });
    }else{
      setState(() {
        _showCancle = false;//隐藏清除按钮
      });
    }
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      color: wechatThemeColor,
      height: 88,
      alignment: Alignment.center,
      child: Column(
        children: [
          Container(
            height: 40,
          ),
          Row(
            children: [
              Container(
                padding: EdgeInsets.only(left: 5,right: 5),
                height: 40,
                width: ScreenWidth(context) - 60,
                margin: EdgeInsets.only(left: 10,bottom: 0),
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(5),
                  color: Colors.white,
                ),
                child: Row(
                  children: [
                    Image.asset('images/放大镜b.png',color: Colors.grey,width: 20,),
                    Expanded(flex: 1,child: TextField(
                      onChanged: _onChange,
                      cursorColor: Colors.green,
                      autofocus: true,//自动聚焦
                      controller: _editController,
                      decoration: InputDecoration(
                        contentPadding: EdgeInsets.only(left: 5,bottom: 10),//文本内容偏移量
                        hintText: '搜索',//无文字时,显示默认文字
                        focusColor: Colors.green,//改变聚焦的颜色
                        border: InputBorder.none,//去掉下边框的线
                        labelStyle: TextStyle(
                          color: Colors.black,
                          fontSize: 16,
                        )

                      ),

                    )),
                    _showCancle == true ? GestureDetector(onTap: (){
                        _editController.clear();//文本置空
                        _onChange('');//文本置空
                      },
                      child: Icon(Icons.cancel,color: Colors.grey,),) : Container(),
                  ],
                ),
              ),
              SizedBox(width: 10,),
              GestureDetector(
                onTap: (){
                  Navigator.of(context).pop();
                },
                child: Text('取消',style: TextStyle(fontSize: 16),),
              )
            ],
          ),

        ],
      ),
    );
  }
}

searchpage引用searchBar

class _SearchPageState extends State<SearchPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          children: [
            SearchBar(),
            Expanded(flex: 1,child: ListView(
            )),
          ],
        )
      ),
    );
  }
}

run

36.png

4.textfiled返回回调,把搜索文本往外传递
class SearchBar extends StatefulWidget {
  //新增回调
  var editBlock = (String text){};
  //构造函数
  SearchBar({
    this.editBlock,
  });

  @override
  _SearchBarState createState() => _SearchBarState();
}
_onChange(String text){
    if(text.length > 0){
      setState(() {
        _showCancle = true;
      });
    }else{
      setState(() {
        _showCancle = false;
      });
    }
    //往外传递回调
    if(widget.editBlock != null){
      widget.editBlock(text);
    }
  }

run

5.为searchPage传递数据,并进行筛选数据
class SearchPage extends StatefulWidget {
  final List<ChatModel> listDatas;
  SearchPage({
    this.listDatas  
  });
  @override
  _SearchPageState createState() => _SearchPageState();
}
class SearchCell extends StatelessWidget {

  final List<ChatModel> listDatas;

  SearchCell({
    this.listDatas,
  });

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTapDown: (e){
        Navigator.of(context).push(
          MaterialPageRoute(builder: (context)=>SearchPage(listDatas: listDatas,))
        );
      },
  }
  ...省略
}

然后在chatPage中传递数据到SearchCell

Widget _cellForIndex(BuildContext context,int index){

     if(index == 0){
       return SearchCell(listDatas: _chatListDatas,);
     }
    ...省略
}

筛选数据

_handleResult(String searchText){
    //先清空搜索结果数据
    _reultDatas.clear();
    if(searchText.length > 0){
      for(int i = 0; i < widget.listDatas.length ; i++){
        ChatModel model =  widget.listDatas[i];
        if(model.name.contains(searchText)){
          _reultDatas.add(model);
        }
      }
    }
    setState(() {
    });
  }
SearchBar(editBlock: (text){
            print('接收到的text是${text}');
            _handleResult(text);
          },),

run

37.png

到此应该全部结束了,完结✿✿ヽ(°▽°)ノ✿


额外补充:

筛选出匹配的文字进行高亮显示

  //对于搜索文字内容进行高亮显示
  Widget _highlightText(String allStr , String searchStr){
    List<TextSpan> spans =  [];
    List<String> strs = allStr.split(searchStr);//文字截取
    for(int i = 0 ; i < strs.length ; i++){
      if(strs[i].length == 0 && i < strs.length-1){
        spans.add(TextSpan(
          text: searchStr,
          style: TextStyle(color: Colors.green,fontSize: 16),
        ));
      }else{
        spans.add(TextSpan(
          text: strs[i],
          style: TextStyle(color: Colors.black,fontSize: 16),
        ));
        if(i < strs.length-1){
          spans.add(TextSpan(
            text: searchStr,
            style: TextStyle(color: Colors.green,fontSize: 16),
          ));
        }
      }
    }
    return RichText(text: TextSpan(
      children: spans,
    ));
  }
Widget _cellForIndex(BuildContext context , int index){
    return ListTile(
      title: _highlightText(_reultDatas[index].name,_searchStr),
      leading: Container(
        width: 50,
        height:50,
        child: Image.network(_reultDatas[index].imageUrl),
      ),
      subtitle: Text(_reultDatas[index].message,overflow: TextOverflow.ellipsis,),
    );
  }

run

38.png

完结✿✿ヽ(°▽°)ノ✿

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容