溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎樣利用Flutter仿寫微信搜索頁效果

發布時間:2022-02-05 15:02:09 來源:億速云 閱讀:210 作者:柒染 欄目:開發技術

小編今天帶大家了解怎樣利用Flutter仿寫微信搜索頁效果,文中知識點介紹的非常詳細。覺得有幫助的朋友可以跟著小編一起瀏覽文章的內容,希望能夠幫助更多想解決這個問題的朋友找到問題的答案,下面跟著小編一起深入學習“怎樣利用Flutter仿寫微信搜索頁效果”的知識吧。

    效果圖

    怎樣利用Flutter仿寫微信搜索頁效果

    如上圖所示,我們用 Flutter 來仿寫搜索頁面,這里聊天首頁點擊搜索欄會跳轉到搜索頁,搜索頁面包含頂部搜索框跟底部 ListView,在搜索框內我們輸入搜索詞會檢索聊天列表模型中 name 屬性中包含搜索詞的模型,并在底部列表中展示,且搜索詞高亮顯示。下面我們分別來介紹下這些功能的實現。

    頂部搜索欄

    怎樣利用Flutter仿寫微信搜索頁效果

    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 部件有兩個比較重要的屬性,onChangedcontroller。onChanged 我們傳入了一個外部方法 _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仿寫微信搜索頁效果”的全部內容了,學會的朋友趕緊操作起來吧。相信億速云小編一定會給大家帶來更優質的文章。謝謝大家對億速云網站的支持!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女