效果图

如上图所示,我们用 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仿写微信搜索页内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

如何利用Flutter仿写微信搜索页效果的更多相关文章

  1. Swift - 自定义UIActivity分享

    UIActivity可以十分方便地将文字、图片等内容进行分享,比如分享到微信、微博、发送邮件、短信等等。下面通过继承UIActivity实现定制按钮和功能,通过调用UIActivityViewController来展示分享框。,NSURL]//新建自定义的分享对象数组acts=[WeiXinActivity(),147)!important;font-family:Consolas,UIActivityTypePrintUIActivityTypeAssignToContactUIActivityType

  2. Flutter中文教程-Cookbook

    Flutter中文网的Cookbook中包含了在编写Flutter应用程序时常见问题及示例。设计基础使用主题共享颜色和字体样式Images显示来自网上的图片用占位符淡入图片使用缓存图Lists创建一个基本list创建一个水平list使用长列表创建不同类型子项的List创建一个gridList处理手势处理点击添加Material触摸水波效果实现滑动关闭导航导航到新页面并返回给新页面传值从新页面返回数据给上一个页面网络从网上获取数据进行认证请求使用WebSockets

  3. android-studio – 未配置Dart SDK

    Initializinggradle…

  4. 安卓 – 从一个扑动的应用程序拨打电话

    或者有更好的选择从我的应用程序拨打电话?

  5. android – 如何在Flutter中添加Webview?

    我知道可以将WebView添加为整页,但找不到任何示例代码.我假设你可以使用PageView作为它的基础,但不知道如何调用本机androidWebView并将其添加到PageView.谁能指出我正确的方向?

  6. android – 如何将消息从Flutter传递给Native?

    如果需要与特定的API/硬件组件进行交互,您如何将Flutter的信息传递回Android/Native代码?是否有任何事件频道可以通过其他方式发送信息或类似于回调?

  7. android – 如何在Flutter App中处理onPause / onResume?

    我是否过于复杂的事情?即使我的用例似乎不需要它,我仍然想知道:如何自己处理onPause/onResume事件?

  8. android – 如何使用Flutter构建Augment Reality应用程序?

    我对Android开发有一些基础知识.最近听说过Flutter并且非常有兴趣研究它.我想知道是否有可能使用颤振构建增强现实应用程序以及要实现此目的的方法?请帮忙.解决方法截至目前,颤振不支持3D.Flutter现在专注于2D,团队长期计划为颤振提供优化的3Dapi.你读了常见问题here.

  9. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  10. php微信公众平台交互与接口详解

    这篇文章主要为大家详细介绍了php微信公众平台开发,交互与接口,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部