如何利用Flutter仿写微信搜索页效果

 更新时间:2022年02月10日 15:48:47   作者:晨曦_iOS  
这篇文章主要给大家介绍了关于如何利用Flutter仿写微信搜索页效果的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

效果图

如上图所示,我们用 Flutter 来仿写搜索页面,这里聊天首页点击搜索栏会跳转到搜索页,搜索页面包含顶部搜索框跟底部 ListView,在搜索框内我们输入搜索词会检索聊天列表模型中 name 属性中包含搜索词的模型,并在底部列表中展示,且搜索词高亮显示。下面我们分别来介绍下这些功能的实现。

顶部搜索栏

class SearchBar extends StatefulWidget {
  final ValueChanged<String>? onChanged;
  const SearchBar({this.onChanged});

  @override
  _SearchBarState createState() => _SearchBarState();
}

class _SearchBarState extends State<SearchBar> {
  final TextEditingController _editingController = TextEditingController();
  bool _showClose = false;
  void _onChange(text) {
    if (null != widget.onChanged) {
      widget.onChanged!(text);
    }
    setState(() {
      _showClose = ((text as String).length > 0);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      height: 84,
      color: CahtThemColor,
      child: Column(
        children: [
          SizedBox(height: 40,), //上半部分留空
          Container(
            height: 44,
            child: Row(
              children: [
                Container(
                  width: screenWidth(context) - 50,
                  height: 34,
                  margin: EdgeInsets.only(left: 5, right: 10),
                  padding: EdgeInsets.only(left: 5, right: 5),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(6.0),
                  ),
                  child: Row(
                    children: [
                      Image(image: AssetImage('images/放大镜b.png'), width: 20, color: Colors.grey,), //放大镜
                      Expanded(child: TextField(
                        controller: _editingController,
                        onChanged: _onChange,
                        autofocus: true,
                        cursorColor: Colors.green,
                        style: TextStyle(
                          fontSize: 16.0,
                          color: Colors.black87,
                          fontWeight: FontWeight.w400,
                        ),
                        decoration: InputDecoration(
                          contentPadding: EdgeInsets.only(left: 5, right: 5, bottom: 12,),
                          border: InputBorder.none,
                          hintText: '搜索',
                          hintStyle: TextStyle(
                            fontSize: 16.0,
                            color: Colors.grey,
                            fontWeight: FontWeight.w400,
                          ),
                        ),
                      ),),
                      if (_showClose) GestureDetector(
                        onTap: () {
                          //清空搜索框
                          _editingController.clear();
                          setState(() {
                            _onChange('');
                          });
                        },
                        child: Icon(
                          Icons.cancel,
                          color: Colors.grey,
                          size: 20,
                        ),
                      ),
                    ],
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  ),
                ), //左边白色背景
                GestureDetector (
                  onTap: () {
                    Navigator.pop(context);
                  },
                  child: Text('取消'),
                ), //右边取消按钮
              ],
            ),
          ), //搜索条部分
        ],
      ),
    );
  }
}

针对搜索页的整体布局我们可以分为顶部的搜索栏跟底部的搜索列表两部分,针对搜索栏我们单独定义了一个 SearchBar 的类来实现,底部搜索列表我们用 Expanded 部件进行了包装。

SearchBar 实现细节

针对 SearchBar 我们这里整体高度设置为了 84,这里最好高度定义为一个变量,根据机型来设置。针对搜索栏我们分为上下两部分,顶部留白及内容部分,顶部留白用 SizedBox 部件实现,底部内容用 Row 部件来实现,分为左边搜索框及右边取消按钮。

左边搜索框实现

搜索框整体部分我们用 Container 部件来实现,可以设置宽、高及圆角属性。child 属性我们也是用 Row 部件来实现,分为左边搜索图标、中间 TextField 及右边 关闭按钮。

TextField 实现细节

TextField 部件有两个比较重要的属性,onChangedcontrolleronChanged 我们传入了一个外部方法 _onChange,可以监听输入框文字的变化,当有文字时展示关闭按钮,没有文字时隐藏关闭按钮。controller 我们传入了一个外部定义的属性 _editingController,可以用来控制 TextField 的编辑。

关闭按钮的实现

关闭按钮我们根据 _showClose 来判断是否展示,且通过 GestureDetector 部件进行包装,点击的时候清空输入框及调用 _onChange 方法,参数传入空字符串,_onChange 方法中字符串为空的时候就会隐藏关闭按钮。

右边取消按钮实现

取消按钮点击的时候就是返回到上一个页面。

内容的检索

我们监听到文字输入框的变化后,就需要进行内容的检索,并且在底部列表中进行展示。

内容的传递

class SearchCell extends StatelessWidget {
  final List<ChatModel>? datas;
  const SearchCell({this.datas});
}
class SearchPage extends StatefulWidget {
  final List<ChatModel>? datas;
  const SearchPage({this.datas});
}

这里我们是基于聊天页面列表数据模型进行检索,找到名称中包含搜索词的模型进行展示。所以我们在 SearchCell 中定义了 datas 属性,并且在 SearchPage 中也定义了 datas 属性,分别在初始化的时候进行传递,这样我们在搜索页面就可以拿到了聊天列表的模型数据。

内容的检索

//满足查找条件的数据数组
  List<ChatModel> _models = [];
  //正在搜索的内容
  String _searchStr = '';
  // 搜索数据查找
  void _searchData(String text) {
    //每次搜索前先清空
    _models.clear();
    _searchStr = text;
    if (text.length < 1) {
      setState(() {});
      return;
    }
    for (int i = 0; i < datas.length; i++) {
      String name = widget.datas?[i].name as String;
      if(name.contains(text)) {
        _models.add(widget.datas?[i] as ChatModel);
      }
    }
    setState(() {});
  }

我们把检索逻辑都抽取到了 _searchData 方法中,输入内容变化的时候调用 _searchData 方法。这里我们定义了一个 _models 数组,专门存放检索数据,我们遍历 datas,把检索到的模型添加到 _models 中。

搜索列表实现

TextStyle _normalStyle = TextStyle(
    fontSize: 16,
    color: Colors.black,
  );
  TextStyle _hightlightedStyle = TextStyle(
    fontSize: 16,
    color: Colors.green,
  );

  Widget _searchTitle(String name) {
    List<TextSpan> textSpans = [];

    List<String> searchStrs = name.split(_searchStr);
    for (int i = 0; i < searchStrs.length; i++) {
      String str = searchStrs[i];
      if (str == '' && i < searchStrs.length - 1) {
        textSpans.add(TextSpan(text: _searchStr, style: _hightlightedStyle));
      } else {
        textSpans.add(TextSpan(text: str, style: _normalStyle));
        if (i < searchStrs.length - 1) {
          textSpans.add(TextSpan(text: _searchStr, style: _hightlightedStyle));
        }
      }
    }
    return RichText(text: TextSpan(children: textSpans));
  }

搜索列表的 cell 就是复用聊天列表的 cell,但是需要变化的是搜索内容的高亮显示,所以 ListTile 部件的 title 属性我们用 RichText 来实现,实现内容这里抽取到了 _searchTitle 方法中。name.split(_searchStr) 会返回一个根据搜索词 _searchStr 进行分割的数组,但是当字符串的开头或者结尾有跟 _searchStr 相同的字符的时候在 searchStrs 数组中的元素就是空字符串,所以我们就需要进行特别判 str == ''。我们循环遍历 searchStrs 数组来创建 TextSpan 部件,并且根据内容是否跟搜索内容一样来分别指定样式 _normalStyle 与 _hightlightedStyle。

总结

到此这篇关于如何利用Flutter仿写微信搜索页效果的文章就介绍到这了,更多相关Flutter仿写微信搜索页内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Android自定义Dialog原理实例解析

    Android自定义Dialog原理实例解析

    这篇文章主要介绍了Android自定义Dialog原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-07-07
  • Android开发手册Chip监听及ChipGroup监听

    Android开发手册Chip监听及ChipGroup监听

    这篇文章主要为大家介绍了Android开发手册Chip监听及ChipGroup监听,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • Android中AsyncTask详细介绍

    Android中AsyncTask详细介绍

    这篇文章主要介绍了Android中AsyncTask详细介绍,AsyncTask是一个很常用的API,尤其异步处理数据并将数据应用到视图的操作场合,需要的朋友可以参考下
    2015-01-01
  • Android uses-permission权限列表中文注释版

    Android uses-permission权限列表中文注释版

    Android有一个精心设计的安全模型。每一个应用都有其自己Linux用户和群组,在单独的进程和VM上运行,不能影响到其他应用
    2014-05-05
  • 简析Android多种AlertDialog对话框效果

    简析Android多种AlertDialog对话框效果

    这篇文章主要为大家介绍了Android多种AlertDialog对话框效果,四种对话框效果一一为大家展示,感兴趣的小伙伴们可以参考一下
    2016-01-01
  • 分析Android Choreographer源码

    分析Android Choreographer源码

    Choreographer的作用主要是配合Vsync,给上层App的渲染提供一个稳定的Message处理的时机,也就是Vsync到来的时候,系统通过对Vsync信号周期的调整,来控制每一帧绘制操作的时机
    2021-06-06
  • Android编程之Animation动画详解

    Android编程之Animation动画详解

    这篇文章主要介绍了Android编程之Animation动画具体用法,结合实例非常详细的总结分析了Android中Animation动画所涉及的相关知识点与动画具体实现技巧,需要的朋友可以参考下
    2016-01-01
  • Android多进程间采用AIDL方式进行通信

    Android多进程间采用AIDL方式进行通信

    这篇文章主要为大家详细介绍了Android多进程间采用AIDL方式进行通信,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • android 通过MediaRecorder实现简单的录音示例

    android 通过MediaRecorder实现简单的录音示例

    本篇文章中主要介绍了android 通过MediaRecorder实现简单的录音示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • Android自定义View详解

    Android自定义View详解

    这篇文章主要为大家详细介绍了Android自定义View,帮助大家战胜Android自定义View,为今后的学习打下基础,感兴趣的小伙伴们可以参考一下
    2016-06-06

最新评论