3.ListView

ListView是最常用的可滾動(dòng)組件之一,它可以沿一個(gè)方向線性排布所有子組件,并且它也支持列表項(xiàng)懶加載(在需要時(shí)才會(huì)創(chuàng)建)

1.默認(rèn)構(gòu)造函數(shù)

我們看看ListView的默認(rèn)構(gòu)造函數(shù)定義:


ListView默認(rèn)構(gòu)造函數(shù)

注意:雖然這種方式將所有children一次性傳遞給 ListView,但子組件)仍然是在需要時(shí)才會(huì)加載(build(如有)忍啸、布局仰坦、繪制),也就是說(shuō)通過(guò)默認(rèn)構(gòu)造函數(shù)構(gòu)建的 ListView 也是基于 Sliver 的列表懶加載模型计雌∏幕危可以看到,雖然使用默認(rèn)構(gòu)造函數(shù)創(chuàng)建的列表也是懶加載的凿滤,但我們還是需要提前將 Widget 創(chuàng)建好妈橄,等到真正需要加載的時(shí)候才會(huì)對(duì) Widget 進(jìn)行布局和繪制。所以我們使用最多還是ListView.builder和ListView.separated

2.ListView.builder

ListView.builder 適合列表項(xiàng)比較多或者列表項(xiàng)不確定的情況翁脆,下面看一下ListView.builder的核心參數(shù)列表:

ListView.builder

  • itemBuilder:它是列表項(xiàng)的構(gòu)建器眷蚓,類(lèi)型為IndexedWidgetBuilder,返回值為一個(gè)widget反番。當(dāng)列表滾動(dòng)到具體的index位置時(shí)沙热,會(huì)調(diào)用該構(gòu)建器構(gòu)建列表項(xiàng)。
  • itemCount:列表項(xiàng)的數(shù)量恬口,如果為null校读,則為無(wú)限列表
ListView.builder實(shí)例

2. ListView.separated

ListView.separated可以在生成的列表項(xiàng)之間添加一個(gè)分割組件,它比ListView.builder多了一個(gè)separatorBuilder參數(shù)祖能,該參數(shù)是一個(gè)分割組件生成器


ListView.separated

3.固定高度列表

前面說(shuō)過(guò)歉秫,給列表指定 itemExtent 或 prototypeItem 會(huì)有更高的性能,所以當(dāng)我們知道列表項(xiàng)的高度都相同時(shí)养铸,強(qiáng)烈建議指定 itemExtent 或 prototypeItem 雁芙。下面看一個(gè)示例

class FixedExtentList extends StatelessWidget {
  const FixedExtentList({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
        prototypeItem: ListTile(title: Text("1")),
      //itemExtent: 56,
      itemBuilder: (context, index) {
        //LayoutLogPrint是一個(gè)自定義組件,在布局時(shí)可以打印當(dāng)前上下文中父組件給子組件的約束信息
        return LayoutLogPrint(
          tag: index, 
          child: ListTile(title: Text("$index")),
        );
      },
    );
  }
}

因?yàn)榱斜眄?xiàng)都是一個(gè) ListTile钞螟,高度相同兔甘,但是我們不知道 ListTile 的高度是多少,所以指定了prototypeItem 鳞滨,運(yùn)行后洞焙,控制臺(tái)打印:


指定itemExtent 或 prototypeItem高度的打印結(jié)果

可見(jiàn) ListTile 的高度是 56 ,所以我們指定 itemExtent 為 56也是可以的澡匪。但是筆者還是建議優(yōu)先指定原型熔任,這樣的話在列表項(xiàng)布局修改后,仍然可以正常工作(前提是每個(gè)列表項(xiàng)的高度相同)唁情。

如果本例中不指定 itemExtent 或 prototypeItem 疑苔,我們看看控制臺(tái)日志信息:


沒(méi)有指定itemExtent 或 prototypeItem高度的打印結(jié)果

可以發(fā)現(xiàn),列表不知道列表項(xiàng)的具體高度甸鸟,高度約束變?yōu)?0.0 到 Infinity惦费,這樣就大大的降低了性能。

4.ListView原理

ListView 內(nèi)部組合了 Scrollable抢韭、Viewport 和 Sliver薪贫,需要注意:

1.ListView 中的列表項(xiàng)組件都是 RenderBox,并不是 Sliver篮绰, 這個(gè)一定要注意后雷。
2.一個(gè) ListView 中只有一個(gè)Sliver,對(duì)列表項(xiàng)進(jìn)行按需加載的邏輯是 Sliver 中實(shí)現(xiàn)的吠各。
3.ListView 的 Sliver 默認(rèn)是 SliverList臀突,如果指定了 itemExtent ,則會(huì)使用 SliverFixedExtentList贾漏;如果 prototypeItem 屬性不為空候学,則會(huì)使用 SliverPrototypeExtentList,無(wú)論是是哪個(gè)纵散,都實(shí)現(xiàn)了子組件的按需加載模型

5.無(wú)限加載列表(上拉加載更多)

第一步: 頂一個(gè)一個(gè)滾動(dòng)控制器

  // 定義一個(gè)的滾動(dòng)控制器梳码,
  // ScrollController間接繼承自Listenable,我們可以根據(jù)ScrollController來(lái)監(jiān)聽(tīng)滾動(dòng)事件
  // 可以用ScrollController來(lái)控制可滾動(dòng)組件的滾動(dòng)位置
ScrollController  scrollController = ScrollController();

第二步: 使用ListView.builder并添加控制器

ListView.builder(
            controller: scrollController,//注意這里一定要加上滾動(dòng)的控制器,否則是無(wú)法監(jiān)聽(tīng)滾動(dòng)元素的
            itemBuilder: (context, index) {
              if(newList?.length == index){
                return LoadingWidget(loadText:loadingText,loadStatus: loadStatus);//自定義加載更多文案伍掀,組件
              }else{
                return Container(
                  padding: const EdgeInsets.all(10.0),
                  decoration: const BoxDecoration(
                      border: Border(
                          bottom: BorderSide(
                              width: 0.5,
                              color: Color(0xffaaaaaa)
                          )
                      )
                  ),
                  child: buildNewListItem(index),//這個(gè)根據(jù)自身需求定義組件
                );
              }
            },
            itemCount: newList!.length + 1 //這個(gè)長(zhǎng)度一定要記得+1 需要包含那個(gè)上拉加載圖標(biāo)
        )

第三步:監(jiān)聽(tīng)控制器

scrollController.addListener(() {
    /**
        調(diào)用 scrollController.position.pixels 可以獲取當(dāng)前滾動(dòng)的像素點(diǎn) ;
        調(diào)用 scrollController.position.maxScrollExtent 可以獲取當(dāng)前最大可滾動(dòng)位置 ;
        如果上述兩個(gè)值相等 , 那么說(shuō)明已經(jīng)滾動(dòng)到列表最底部了 , 此時(shí)可以執(zhí)行上拉加載更多
     */
    dynamic maxScroll = scrollController.position.maxScrollExtent;
    dynamic pixels = scrollController.position.pixels;
    if(maxScroll == pixels){
     //加載更多  
     //TODO
    }
  });

6.添加固定列表頭

@override
Widget build(BuildContext context) {
  return Column(children: <Widget>[
    ListTile(title:Text("資訊中心")),
    Expanded(
      child: ListView.builder(itemBuilder: (BuildContext context, int index) {
        return ListTile(title: Text("$index"));
      }),
    ),
  ]);
}
固定列表頭
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載掰茶,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。
  • 序言:七十年代末蜜笤,一起剝皮案震驚了整個(gè)濱河市濒蒋,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌把兔,老刑警劉巖沪伙,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異县好,居然都是意外死亡围橡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)缕贡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)翁授,“玉大人拣播,你說(shuō)我怎么就攤上這事∈詹粒” “怎么了诫尽?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)炬守。 經(jīng)常有香客問(wèn)我,道長(zhǎng)剂跟,這世上最難降的妖魔是什么减途? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮曹洽,結(jié)果婚禮上鳍置,老公的妹妹穿的比我還像新娘。我一直安慰自己送淆,他們只是感情好税产,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著偷崩,像睡著了一般辟拷。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阐斜,一...
    開(kāi)封第一講書(shū)人閱讀 51,688評(píng)論 1 305
  • 那天衫冻,我揣著相機(jī)與錄音,去河邊找鬼谒出。 笑死隅俘,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笤喳。 我是一名探鬼主播为居,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼杀狡!你這毒婦竟也來(lái)了蒙畴?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捣卤,失蹤者是張志新(化名)和其女友劉穎忍抽,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體董朝,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸠项,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了子姜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片祟绊。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡楼入,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出牧抽,到底是詐尸還是另有隱情嘉熊,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布扬舒,位于F島的核電站阐肤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏讲坎。R本人自食惡果不足惜孕惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望晨炕。 院中可真熱鬧衫画,春花似錦、人聲如沸瓮栗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)费奸。三九已至弥激,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間愿阐,已是汗流浹背秆撮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留换况,地道東北人职辨。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像戈二,于是被迫代替她去往敵國(guó)和親舒裤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容