Flutter 滾動(dòng)組件之ListView

介紹

線性排列的可滾動(dòng)列表。

核心屬性

ListView({
    Key? key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController? controller,
    bool? primary,
    ScrollPhysics? physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry? padding,
    this.itemExtent,
    this.prototypeItem,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double? cacheExtent,
    List<Widget> children = const <Widget>[],
    int? semanticChildCount,
    DragStartBehavior dragStartBehavior = DragStartBehavior.start,
    ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
    String? restorationId,
    Clip clipBehavior = Clip.hardEdge,
  })
  1. scrollDirection
    設(shè)置滾動(dòng)方向,其值有:
enum Axis {
  /// 水平方向滾動(dòng),默認(rèn)
  horizontal,
  /// 豎直方向滾動(dòng)
  vertical,
}
  1. controller
    滾動(dòng)控制器。能夠獲取滾動(dòng)相關(guān)信息
  2. primary
    當(dāng)內(nèi)容不足以滾動(dòng)時(shí),是否支持滾動(dòng);true:用來解決listView不滿一頁(yè)無(wú)法觸發(fā)下拉刷新,需要注意這個(gè)時(shí)候不可以設(shè)置controller
  3. physics:控制用戶滾動(dòng)視圖的交互,可以提供邊界回彈特效
  • AlwaysScrollableScrollPhysics:列表總是可滾動(dòng)的。在iOS上會(huì)有回彈效果,在android上不會(huì)回彈。那么問題來了,如果primary設(shè)置為false(內(nèi)容不足時(shí)不滾動(dòng)),且 physics設(shè)置為AlwaysScrollableScrollPhysics,列表也是是可以滑動(dòng)的
  • PageScrollPhysics:一般是給PageView控件用的滑動(dòng)效果。如果listview設(shè)置的話在滑動(dòng)到末尾時(shí)會(huì)有個(gè)比較大的彈起和回彈
  • ClampingScrollPhysics:滾動(dòng)時(shí)沒有回彈效果,同android系統(tǒng)的listview效果
  • NeverScrollableScrollPhysics:就算內(nèi)容超過列表范圍也不會(huì)滑動(dòng)
  • BouncingScrollPhysics:不論什么平臺(tái)都會(huì)有回彈效果
  1. shrinkWrap
    默認(rèn)false:則高度為滑動(dòng)方向上的最大允許高度;如果在滑動(dòng)方向上沒有設(shè)置約束,則這個(gè)字段必須設(shè)置為true,否則會(huì)報(bào)錯(cuò)。簡(jiǎn)而言之就是父節(jié)點(diǎn)為滑動(dòng)組件的時(shí)候,且滑動(dòng)方向一致需要true,例如:SingleChildScrollView。
  2. padding
    內(nèi)邊距
  3. itemExtent
    指定Item在滑動(dòng)方向上的高度,用來提高滑動(dòng)性能。指定了該屬性后,Item自己定的高度將失效。
  4. prototypeItem
    指定Item在滑動(dòng)方向上的高度為prototypeItem屬性的widget的高度,用來提高滑動(dòng)性能。指定了該屬性后,Item自己定的高度將失效。
  5. addAutomaticKeepAlives
    是否將子控件包裹在AutomaticKeepAlive控件內(nèi)。
  6. addRepaintBoundaries
    是否將子控件包裹在 RepaintBoundary 控件內(nèi)。用于避免列表滾動(dòng)時(shí)的重繪,如果子控件重繪開銷很小時(shí),比如子控件就是個(gè)色塊或簡(jiǎn)短的文字,把這個(gè)字段設(shè)置為false性能會(huì)更好
  7. cacheExtent
    可見區(qū)域的前后會(huì)有一定高度的空間去緩存子控件,當(dāng)滑動(dòng)時(shí)就可以迅速呈現(xiàn)
  8. children
    子控件數(shù)組

示例

ListView有四種使用方式:

  1. ListView()
    默認(rèn)構(gòu)造方法,可以在子組件比較少時(shí)使用,因?yàn)椴还茏咏M件是否可見,都會(huì)創(chuàng)建出所有child。
ListView(
    children: [
      Container(
        height: 300,
        color: Colors.pink,
        child: const Center(child: Text("This is a item1"),),
      ),
      Container(
        height: 300,
        color: Colors.teal,
        child: const Center(child: Text("This is a item2"),),
      ),
      Container(
        height: 300,
        color: Colors.amber,
        child: const Center(child: Text("This is a item3"),),
      ),
    ],
  );
  1. ListView.builder()
    這種方式屬于懶加載方式,比較常用。傳參數(shù)跟ListView()差不多,區(qū)別是沒有children屬性,代替的是 itemBuilder 和 itemCount
  • itemBuilder:IndexedWidgetBuilder Function類型,創(chuàng)建子組件
  • itemCount:item數(shù)量
ListView.builder(itemBuilder: (context, index) {
    Color? color;
    if (index % 2 == 0) {
      color = Colors.pink;
    } else if (index % 3 == 0) {
      color = Colors.teal;
    } else if (index % 5 == 0) {
      color = Colors.amber;
    }
    return Container(
      height: 100,
      color: color,
      child: Center(child: Text("This is a item:$index"),),
    );
  }, itemCount: 50, itemExtent: 200,);
  1. ListView.separated()
    跟ListView.builder()差不多,可以設(shè)置分割線,需要傳一個(gè)separatorBuilder。
ListView.separated(
    itemBuilder: (context, index) {
      Color? color;
      if (index % 2 == 0) {
        color = Colors.pink;
      } else if (index % 3 == 0) {
        color = Colors.teal;
      } else if (index % 5 == 0) {
        color = Colors.amber;
      }
      return Container(
        height: 100,
        color: color,
        child: Center(
          child: Text("This is a item:$index"),
        ),
      );
    },
    separatorBuilder: (context, index) {
      return const Divider();
    },
    itemCount: 50,
  );
  1. ListView.custom()
    這個(gè)是比較高階的用法了,可以自己去實(shí)現(xiàn)子控件的復(fù)用重繪。這里就不展開說了
  • childrenDelegate:SliverChildDelegate;有兩個(gè)默認(rèn)實(shí)現(xiàn)SliverChildListDelegate,SliverChildBuilderDelegate;方式1實(shí)際上內(nèi)部實(shí)現(xiàn)是SliverChildListDelegate,方式2,3內(nèi)部實(shí)現(xiàn)是SliverChildBuilderDelegate;
    效果圖:


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容