如何利用Flutter仿寫微信搜索頁效果
效果圖
如上圖所示,我們用 Flutter 來仿寫搜索頁面,這里聊天首頁點(diǎn)擊搜索欄會(huì)跳轉(zhuǎn)到搜索頁,搜索頁面包含頂部搜索框跟底部 ListView,在搜索框內(nèi)我們輸入搜索詞會(huì)檢索聊天列表模型中 name 屬性中包含搜索詞的模型,并在底部列表中展示,且搜索詞高亮顯示。下面我們分別來介紹下這些功能的實(shí)現(xiàn)。
頂部搜索欄
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('取消'), ), //右邊取消按鈕 ], ), ), //搜索條部分 ], ), ); } }
針對(duì)搜索頁的整體布局我們可以分為頂部的搜索欄跟底部的搜索列表兩部分,針對(duì)搜索欄我們單獨(dú)定義了一個(gè) SearchBar 的類來實(shí)現(xiàn),底部搜索列表我們用 Expanded 部件進(jìn)行了包裝。
SearchBar 實(shí)現(xiàn)細(xì)節(jié)
針對(duì) SearchBar 我們這里整體高度設(shè)置為了 84,這里最好高度定義為一個(gè)變量,根據(jù)機(jī)型來設(shè)置。針對(duì)搜索欄我們分為上下兩部分,頂部留白及內(nèi)容部分,頂部留白用 SizedBox 部件實(shí)現(xiàn),底部內(nèi)容用 Row 部件來實(shí)現(xiàn),分為左邊搜索框及右邊取消按鈕。
左邊搜索框?qū)崿F(xiàn)
搜索框整體部分我們用 Container 部件來實(shí)現(xiàn),可以設(shè)置寬、高及圓角屬性。child 屬性我們也是用 Row 部件來實(shí)現(xiàn),分為左邊搜索圖標(biāo)、中間 TextField 及右邊 關(guān)閉按鈕。
TextField 實(shí)現(xiàn)細(xì)節(jié)
TextField
部件有兩個(gè)比較重要的屬性,onChanged
跟 controller
。onChanged
我們傳入了一個(gè)外部方法 _onChange
,可以監(jiān)聽輸入框文字的變化,當(dāng)有文字時(shí)展示關(guān)閉按鈕,沒有文字時(shí)隱藏關(guān)閉按鈕。controller
我們傳入了一個(gè)外部定義的屬性 _editingController
,可以用來控制 TextField
的編輯。
關(guān)閉按鈕的實(shí)現(xiàn)
關(guān)閉按鈕我們根據(jù) _showClose
來判斷是否展示,且通過 GestureDetector
部件進(jìn)行包裝,點(diǎn)擊的時(shí)候清空輸入框及調(diào)用 _onChange
方法,參數(shù)傳入空字符串,_onChange
方法中字符串為空的時(shí)候就會(huì)隱藏關(guān)閉按鈕。
右邊取消按鈕實(shí)現(xiàn)
取消按鈕點(diǎn)擊的時(shí)候就是返回到上一個(gè)頁面。
內(nèi)容的檢索
我們監(jiān)聽到文字輸入框的變化后,就需要進(jìn)行內(nèi)容的檢索,并且在底部列表中進(jìn)行展示。
內(nèi)容的傳遞
class SearchCell extends StatelessWidget { final List<ChatModel>? datas; const SearchCell({this.datas}); }
class SearchPage extends StatefulWidget { final List<ChatModel>? datas; const SearchPage({this.datas}); }
這里我們是基于聊天頁面列表數(shù)據(jù)模型進(jìn)行檢索,找到名稱中包含搜索詞的模型進(jìn)行展示。所以我們?cè)?SearchCell 中定義了 datas 屬性,并且在 SearchPage 中也定義了 datas 屬性,分別在初始化的時(shí)候進(jìn)行傳遞,這樣我們?cè)谒阉黜撁婢涂梢阅玫搅肆奶炝斜淼哪P蛿?shù)據(jù)。
內(nèi)容的檢索
//滿足查找條件的數(shù)據(jù)數(shù)組 List<ChatModel> _models = []; //正在搜索的內(nèi)容 String _searchStr = ''; // 搜索數(shù)據(jù)查找 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 方法中,輸入內(nèi)容變化的時(shí)候調(diào)用 _searchData 方法。這里我們定義了一個(gè) _models 數(shù)組,專門存放檢索數(shù)據(jù),我們遍歷 datas,把檢索到的模型添加到 _models 中。
搜索列表實(shí)現(xiàn)
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 就是復(fù)用聊天列表的 cell,但是需要變化的是搜索內(nèi)容的高亮顯示,所以 ListTile 部件的 title 屬性我們用 RichText 來實(shí)現(xiàn),實(shí)現(xiàn)內(nèi)容這里抽取到了 _searchTitle 方法中。name.split(_searchStr) 會(huì)返回一個(gè)根據(jù)搜索詞 _searchStr 進(jìn)行分割的數(shù)組,但是當(dāng)字符串的開頭或者結(jié)尾有跟 _searchStr 相同的字符的時(shí)候在 searchStrs 數(shù)組中的元素就是空字符串,所以我們就需要進(jìn)行特別判 str == ''。我們循環(huán)遍歷 searchStrs 數(shù)組來創(chuàng)建 TextSpan 部件,并且根據(jù)內(nèi)容是否跟搜索內(nèi)容一樣來分別指定樣式 _normalStyle 與 _hightlightedStyle。
總結(jié)
到此這篇關(guān)于如何利用Flutter仿寫微信搜索頁效果的文章就介紹到這了,更多相關(guān)Flutter仿寫微信搜索頁內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android開發(fā)手冊(cè)Chip監(jiān)聽及ChipGroup監(jiān)聽
這篇文章主要為大家介紹了Android開發(fā)手冊(cè)Chip監(jiān)聽及ChipGroup監(jiān)聽,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06Android uses-permission權(quán)限列表中文注釋版
Android有一個(gè)精心設(shè)計(jì)的安全模型。每一個(gè)應(yīng)用都有其自己Linux用戶和群組,在單獨(dú)的進(jìn)程和VM上運(yùn)行,不能影響到其他應(yīng)用2014-05-05簡(jiǎn)析Android多種AlertDialog對(duì)話框效果
這篇文章主要為大家介紹了Android多種AlertDialog對(duì)話框效果,四種對(duì)話框效果一一為大家展示,感興趣的小伙伴們可以參考一下2016-01-01Android多進(jìn)程間采用AIDL方式進(jìn)行通信
這篇文章主要為大家詳細(xì)介紹了Android多進(jìn)程間采用AIDL方式進(jìn)行通信,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04android 通過MediaRecorder實(shí)現(xiàn)簡(jiǎn)單的錄音示例
本篇文章中主要介紹了android 通過MediaRecorder實(shí)現(xiàn)簡(jiǎn)單的錄音示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-02-02