上一篇文章我们已经完成首页聊天页面的导航条和列表展示,今天的任务是完成搜索cell的展示和点击之后的搜索页面的功能。
自定义SearchCell
新建search_cell.dart文件
实现SearchCell代码
SearchCell的话,因为仅仅只是展示,点击之后就进入搜索页了,应该来说是不需要状态的,所以用一个StatelessWidget就够了。然后布局的方式使用一个Container包含一个Row,Row里面包一个图片和文本就可以了。布局的方式其实多种多样,能实现就好了。完整代码如下:
一个有意思的地方是,flutter里面的Image居然可以设置颜色,而且颜色是设置给图片的。比如我的放大镜图片原本是黑色的,设置红色之后,居然真的变红色了!!!
使用SearchCell
SearchCell的展示就算写完了,然后在ChatPage.dart中使用,我们把ListView的itemBuilder方法抽取出来,然后因为我们多加了一个SearchCell,所以itemCount需要加1,然后取_chatList数据的时候也要处理一下下标。
自定义SearchPage
新建search_page.dart文件
简单实现SearchPage
SearchPage作为一个页面,使用StatelessWidget肯定是无法胜任的,所以使用一个StatefulWidget。而由于AppBar的样式和我们需要显示的效果图还是有差别的,所以这里我们不使用Scaffold提供的AppBar了。我们自定义一个SearchBar,配合一个ListView来搭建基本的布局。这里面基本没有新鲜的东西,就简单贴一下代码:
SearchBar由于是在SearchPage中使用的,所以就直接定义在SearchPage中了,代码也是先简单定义如下:
点击跳转到SearchPage
在搜索cell里面实现点击方法,然后跳转到SearchPage,显示效果如图:
实现SearchBar
SearchBar的布局
SearchBar的布局,最外层分为上下两个部分,上面的部分是系统状态栏的高度。下面的部分就是显示搜索条的高度。而搜索条的布局,使用Row分隔为左右两个部分,左侧包含放大镜,文本输入框和删除图片。右侧就是一个返回上级页面的取消。这里主要提一下flutter中的文本框,跟iOS中UITextField真的很不一样,UITextField中左侧的图标,右侧的删除,都是封装在内部的。而在flutter中,文本框TextField真的就只有文本框,没有其他的东西,都需要自己添加。完整代码如下:
SearchBar事件处理
取消的处理
点击取消需要pop到上一个界面,给取消加一个GestureDetector
实现onTap
就好了。代码如下:
清除按钮功能实现
首先作为一个开发者,有一个学习的氛围跟一个交流圈子特别重要,这是一个我的iOS开发公众号: 编程大鑫,不管你是小白还是大牛都欢迎入驻 ,让我们一起进步,共同发展!(群内会免费提供一些群主收藏的免费学习书籍资料以及整理好的几百道面试题和答案文档!)
未输入文本的时候,不显示清除按钮。有输入文本的时候,显示清除按钮。点击清除按钮,清空文本内容并隐藏清除按钮。
使用一个bool值_showClear
控制清除按钮的显示隐藏。代码如下:
在文本变化的时候,修改_showClear
值并刷新状态。文本的变化在TextField的onChanged
属性就可以监听到。代码如下:
最后就是清除按钮的点击功能,由于需要清空TextField的文本内容,需要使用到TextEditingController
,给TextField的controller
属性赋值,然后通过TextEditingController
对象清除文本内容。文本清除之后并不会自动调用系统的onChanged
方法,自己手动调用一下就好了。代码如下:
SearchBar回调文本框的内容
文本框的内容变化的时候,需要回调给SearchBar外部,这样我们才能在SearchPage页面进行搜索内容。使用一个回调作为参数就可以实现了。代码如下:
onChanged
是一个闭包属性,在初始化SearchBar的时候传入,在TextField的文本变化的时候调用闭包,并将文本作为参数回传给SearchBar外部。因为将onChanged
作为了必传参数,所以编译器自然会在用到了SearchBar的地方报错。很容易找到报错的地方,加个参数就好了。
SearchBar相关的代码就算差不多完成了,其实可以将SearchBar单独作为一个文件独立出来。接下来就是处理SearchPage了
实现SearchPage
搜索页面的搜索功能,往细了说,可以搜索很多内容,我们这里只是简单的搜索名字,只要名字包含输入的内容,就将搜索结果展示出来。由于这里对中文名进行搜索的时候,能匹配到的数据比较少,所以这里已经将网络请求返回的名字由中文改为英文名字了。前面展示中文名字的截图就不做修改了。
SearchPage的搜索功能
添加datas
数据源
要实现SearchPage的搜索功能,那么它首先必须要有数据源,很明显它的数据源是从首页来的。先定义一个datas
,作为必传参数,然后通过外部层层传递过来。
datas
定义好了以后,报红色错误的地方,就是需要传参数的地方,很方便,都不用我们自己去翻哪里需要加参数了。发现SearchCell里面需要传入数据源,同样的方式,在SearchCell里面定义datas
,然后在报错的地方处理。
就这样子顺藤摸瓜,直到来到chat_page将数据源传入就完成了
SearchPage自己的数据源
SearchPage需要展示搜索之后的结果,所以自己定义一个数组用来存放搜索的结果。并且暂时先使用Text做一个最简单的展示。代码如下:
实现搜索功能并展示数据
搜索的功能实现很简单,就是判断数据源里面的名字是否包含输入的文本,如果包含就全部添加并展示。 代码如下:
APP上如图,我输入son,显示结果:
SearchPage的搜索结果列表展示
SearchPage的搜索结果列表展示的数据样式,应该和首页是类似的。所以可以直接使用首页的布局。代码如下:
SearchPage高亮显示搜到的结果
这里的思路是,高亮显示搜到的结果,那么普通的文本肯定是不行了,必须是富文本。如何找到搜索的关键字在文本中的位置呢,这个不用我们考虑了。flutter中对字符串有一个分隔方法split
,这个方法跟iOS中的字符串的componentsSeparatedByString:
方法类似,根据传入的参数来分隔字符串。这里贴一下iOS的代码:
(还是Xcode看着顺眼啊)我们将字符串abcaa
以字符a
分组,再将分组的结果拼接回原来的字符串。为什么要这么操作?因为重新拼接新字符串的时候,我们就可以处理富文本字符串了。现在回到flutter中来,flutter中拼接的富文本的方式太方便了,RichText花样拼接TextSpan这个我们在前面也讲过了。
_searchKey
就是我们输入的文本,在SearchPage中声明属性,在SearchBar的回调中赋值就好了。
现在测试一下,输入son,APP显示如图:
滚动列表叫回键盘
ListView的滚动,我们在前面已经说过一次,需要将ListView包在NotificationListener
里面。然后叫回键盘的代码FocusScope.of(context).requestFocus(FocusNode());
这个记住就好了,代码如下:
总结
到这里我们的flutter仿微信Demo功能就差不多完了,还剩最后一篇就是介绍flutter和原生混合开发的一些东西。这个也是实际项目中应该经常会遇到的情况。其实写到这里会发现很多东西和原生都是相通的或者类似的。除了新的语言Dart不是很熟悉之外,其他很多地方比如很多属性的名字,颜色,闭包,都能够看到原生的影子。flutter创造者们也不会闭门造车,都会去借鉴原生里面的东西。