最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何利用Flutter仿寫微信搜索頁(yè)效果

 更新時(shí)間:2022年02月10日 15:48:47   作者:晨曦_iOS  
這篇文章主要給大家介紹了關(guān)于如何利用Flutter仿寫微信搜索頁(yè)效果的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下

效果圖

如上圖所示,我們用 Flutter 來(lái)仿寫搜索頁(yè)面,這里聊天首頁(yè)點(diǎn)擊搜索欄會(huì)跳轉(zhuǎn)到搜索頁(yè),搜索頁(yè)面包含頂部搜索框跟底部 ListView,在搜索框內(nèi)我們輸入搜索詞會(huì)檢索聊天列表模型中 name 屬性中包含搜索詞的模型,并在底部列表中展示,且搜索詞高亮顯示。下面我們分別來(lái)介紹下這些功能的實(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ì)搜索頁(yè)的整體布局我們可以分為頂部的搜索欄跟底部的搜索列表兩部分,針對(duì)搜索欄我們單獨(dú)定義了一個(gè) SearchBar 的類來(lái)實(shí)現(xiàn),底部搜索列表我們用 Expanded 部件進(jìn)行了包裝。

SearchBar 實(shí)現(xiàn)細(xì)節(jié)

針對(duì) SearchBar 我們這里整體高度設(shè)置為了 84,這里最好高度定義為一個(gè)變量,根據(jù)機(jī)型來(lái)設(shè)置。針對(duì)搜索欄我們分為上下兩部分,頂部留白及內(nèi)容部分,頂部留白用 SizedBox 部件實(shí)現(xiàn),底部?jī)?nèi)容用 Row 部件來(lái)實(shí)現(xiàn),分為左邊搜索框及右邊取消按鈕。

左邊搜索框?qū)崿F(xiàn)

搜索框整體部分我們用 Container 部件來(lái)實(shí)現(xiàn),可以設(shè)置寬、高及圓角屬性。child 屬性我們也是用 Row 部件來(lái)實(shí)現(xiàn),分為左邊搜索圖標(biāo)、中間 TextField 及右邊 關(guān)閉按鈕。

TextField 實(shí)現(xiàn)細(xì)節(jié)

TextField 部件有兩個(gè)比較重要的屬性,onChangedcontroller。onChanged 我們傳入了一個(gè)外部方法 _onChange,可以監(jiān)聽(tīng)輸入框文字的變化,當(dāng)有文字時(shí)展示關(guān)閉按鈕,沒(méi)有文字時(shí)隱藏關(guān)閉按鈕。controller 我們傳入了一個(gè)外部定義的屬性 _editingController,可以用來(lái)控制 TextField 的編輯。

關(guān)閉按鈕的實(shí)現(xiàn)

關(guān)閉按鈕我們根據(jù) _showClose 來(lái)判斷是否展示,且通過(guò) GestureDetector 部件進(jìn)行包裝,點(diǎn)擊的時(shí)候清空輸入框及調(diào)用 _onChange 方法,參數(shù)傳入空字符串,_onChange 方法中字符串為空的時(shí)候就會(huì)隱藏關(guān)閉按鈕。

右邊取消按鈕實(shí)現(xiàn)

取消按鈕點(diǎn)擊的時(shí)候就是返回到上一個(gè)頁(yè)面。

內(nèi)容的檢索

我們監(jiān)聽(tīng)到文字輸入框的變化后,就需要進(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});
}

這里我們是基于聊天頁(yè)面列表數(shù)據(jù)模型進(jìn)行檢索,找到名稱中包含搜索詞的模型進(jìn)行展示。所以我們?cè)?SearchCell 中定義了 datas 屬性,并且在 SearchPage 中也定義了 datas 屬性,分別在初始化的時(shí)候進(jìn)行傳遞,這樣我們?cè)谒阉黜?yè)面就可以拿到了聊天列表的模型數(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 來(lái)實(shí)現(xiàn),實(shí)現(xiàn)內(nèi)容這里抽取到了 _searchTitle 方法中。name.split(_searchStr) 會(huì)返回一個(gè)根據(jù)搜索詞 _searchStr 進(jìn)行分割的數(shù)組,但是當(dāng)字符串的開(kāi)頭或者結(jié)尾有跟 _searchStr 相同的字符的時(shí)候在 searchStrs 數(shù)組中的元素就是空字符串,所以我們就需要進(jìn)行特別判 str == ''。我們循環(huán)遍歷 searchStrs 數(shù)組來(lái)創(chuàng)建 TextSpan 部件,并且根據(jù)內(nèi)容是否跟搜索內(nèi)容一樣來(lái)分別指定樣式 _normalStyle 與 _hightlightedStyle。

總結(jié)

到此這篇關(guān)于如何利用Flutter仿寫微信搜索頁(yè)效果的文章就介紹到這了,更多相關(guān)Flutter仿寫微信搜索頁(yè)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android獲取手機(jī)位置的實(shí)現(xiàn)代碼

    Android獲取手機(jī)位置的實(shí)現(xiàn)代碼

    這篇文章主要為大家詳細(xì)介紹了Android獲取手機(jī)位置的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • Android 實(shí)現(xiàn)手機(jī)接通電話后振動(dòng)提示的功能

    Android 實(shí)現(xiàn)手機(jī)接通電話后振動(dòng)提示的功能

    本文主要介紹Android 實(shí)現(xiàn)手機(jī)接通電話后振動(dòng)提示的功能,這里整理了詳細(xì)的相關(guān)資料,并附有示例代碼,有需要的朋友可以參考下
    2016-08-08
  • Android SwipeRefreshLayout超詳細(xì)講解

    Android SwipeRefreshLayout超詳細(xì)講解

    在android開(kāi)發(fā)中,使用最多的數(shù)據(jù)刷新方式就是下拉刷新了,而完成此功能我們使用最多的就是第三方的開(kāi)源庫(kù)PullToRefresh。現(xiàn)如今,google也忍不住推出了自己的下拉組件SwipeRefreshLayout,下面我們通過(guò)api文檔和源碼來(lái)分析學(xué)習(xí)如何使用SwipeRefreshLayout
    2022-11-11
  • android開(kāi)發(fā)之Json文件的讀寫的示例代碼

    android開(kāi)發(fā)之Json文件的讀寫的示例代碼

    這篇文章主要介紹了android開(kāi)發(fā)之Json文件的讀寫的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • Android中Hilt的使用詳解

    Android中Hilt的使用詳解

    Hilt?是?Android?的依賴項(xiàng)注入庫(kù),可減少在項(xiàng)目中執(zhí)行手動(dòng)依賴項(xiàng)注入的樣板代碼,本文就來(lái)為大家介紹一下Hilt的具體使用吧,希望對(duì)大家有所幫助
    2023-06-06
  • Android編程設(shè)計(jì)模式之單例模式實(shí)例詳解

    Android編程設(shè)計(jì)模式之單例模式實(shí)例詳解

    這篇文章主要介紹了Android編程設(shè)計(jì)模式之單例模式,結(jié)合實(shí)例形式詳細(xì)分析了Android開(kāi)發(fā)設(shè)計(jì)模式中單例模式的概念、功能、實(shí)現(xiàn)、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-12-12
  • 基于Android中獲取資源的id和url方法總結(jié)

    基于Android中獲取資源的id和url方法總結(jié)

    下面小編就為大家分享一篇基于Android中獲取資源的id和url方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • 如何使用Flutter發(fā)布安卓應(yīng)用

    如何使用Flutter發(fā)布安卓應(yīng)用

    應(yīng)用開(kāi)發(fā)完了,當(dāng)然需要發(fā)布了,下面來(lái)看看用 Flutter 開(kāi)發(fā)的應(yīng)用如何發(fā)布,本文只關(guān)注 Android 版本的發(fā)布
    2021-05-05
  • android實(shí)現(xiàn)查詢公交車還有幾站的功能

    android實(shí)現(xiàn)查詢公交車還有幾站的功能

    這篇文章主要為大家詳細(xì)介紹了android實(shí)現(xiàn)查詢公交車還有幾站的功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android開(kāi)發(fā)之ImageLoader本地緩存

    Android開(kāi)發(fā)之ImageLoader本地緩存

    ImageLoader是一個(gè)圖片緩存的開(kāi)源庫(kù),提供了強(qiáng)大的圖片緩存機(jī)制,很多開(kāi)發(fā)者都在使用,今天給大家介紹Android開(kāi)發(fā)之ImageLoader本地緩存。對(duì)imageloader本地緩存相關(guān)知識(shí)感興趣的朋友一起學(xué)習(xí)吧
    2016-01-01

最新評(píng)論

成武县| 周口市| 商都县| 新宁县| 塘沽区| 安徽省| 延津县| 桃园县| 永仁县| 图木舒克市| 平谷区| 马关县| 赞皇县| 枣强县| 赤城县| 铁岭县| 海伦市| 进贤县| 武胜县| 岳阳市| 景德镇市| 十堰市| 长岛县| 莒南县| 浦东新区| 岳池县| 古丈县| 上饶市| 尚志市| 高台县| 河西区| 灵川县| 桐庐县| 繁峙县| 宁强县| 托克逊县| 宁蒗| 平昌县| 齐齐哈尔市| 瑞安市| 太白县|