Flutter ListView控件

ListView是flutter中线性排列的可滚动的列表部件。ListView 是最常用的滚动小部件。它在滚动方向上一个接一个地显示其子项。在交叉轴上,子项需要填满 ListView。

如果非空,则 itemExtent 会强制子项在滚动方向上具有给定的范围。

如果非空,则prototypeItem 会强制子项在滚动方向上具有与给定小部件相同的范围。 指定 itemExtent 或prototypeItem 比让子项确定自己的范围更有效,因为滚动机制可以利用对子项范围的预知来节省工作,例如当滚动位置发生剧烈变化时。 您不能同时指定 itemExtent 和prototypeItem,只能指定其中一个或不指定其中任何一个。

构建 ListView 有四种选项

1.默认构造函数采用显式 List<Widget> 子项

此构造函数适用于子项数量较少的列表视图,因为构造 List 需要为列表视图中可能显示的每个子项(而不仅仅是实际可见的子项)执行工作。默认 List 方式,是把数据添加到列表中,然后直接添加到 ListView。 Tips: 如果需要设置分割线,使用ListTile.divideTiles。

Dart 复制代码
 child: ListView(
          padding: const EdgeInsets.all(8),
          children: <Widget>[
            Container(
              height: 50,
              color: Colors.amber[600],
              child: const Center(child: Text("Entry A")),
            ),
            Container(
              height: 50,
              color: Colors.amber[500],
              child: const Center(child: Text("Entry B")),
            ),
            Container(
              height: 50,
              color: Colors.amber[100],
              child: const Center(child: Text("Entry C")),
            )
          ],
        )

2.ListView.builder 构造函数采用 IndexedWidgetBuilder,它根据需要构建子项

此构造函数适用于子项数量较多(或无限)的列表视图,因为仅对实际可见的子项调用构建器。

Dart 复制代码
 child: ListView.builder(
          controller: _scrollController,
          itemBuilder: (context, index) {
            return Card(
              child: Container(
                height: 60,
                alignment: Alignment.centerLeft,
                child: Text("Item $index"),
              ),
            );
          },
          itemCount: 200,
        ),

如果要添加分割线可以通过一个Column包裹Container和一个Divider。

Dart 复制代码
    child: ListView.builder(
          controller: _scrollController,
          itemBuilder: (context, index) {
            return Card(
              child:Column(
                children: [
                Container(
                    height: 60,
                    alignment: Alignment.centerLeft,
                    child: Text("Item $index"),
                  ),
                  new Divider()
                ],
              ),
            );
          },

3.ListView.separated 构造函数采用两个 IndexedWidgetBuilder:itemBuilder 根据需要构建子项,separatorBuilder 类似地构建出现在子项之间的分隔符子项

此构造函数适用于子项数量固定的列表视图。通过 separatorBuilder 直接添加分割线。

Dart 复制代码
  final List<String> entries = <String>['C', 'Y', 'Z', 'Y'];
  final List<int> colorCodes = <int>[600, 500, 300, 100];

 
 child: ListView.separated(
            itemBuilder: (BuildContext context, int index) {
              return Container(
                height: 50,
                color: Colors.amber[colorCodes[index]],
                child: Center(child: Text('Entry ${entries[index]}')),
              );
            },
            separatorBuilder: (context, index) {
              return const Divider();
            },
            itemCount: entries.length),

4.ListView.custom 构造函数采用 SliverChildDelegate,它提供了自定义子模型其他方面的功能。

例如,SliverChildDelegate 可以控制用于估计实际不可见的子项大小的算法。

Dart 复制代码
List<String> entries = <String>['C', 'Y', 'Z', 'Y'];

class KeepAliveItem extends StatelessWidget {
  const KeepAliveItem({
    required Key super.key,
    required this.data,
  });

  final String data;

  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      child: Text(data),
    );
  }
}

    child: ListView.custom(
            childrenDelegate: SliverChildBuilderDelegate(
          (BuildContext context, int index) {
            return KeepAliveItem(
              data: entries[index],
              key: ValueKey<String>(entries[index]),
            );
          },
          childCount: entries.length,
        ))

ScrollController

要控制滚动视图的初始滚动偏移,请提供一个已设置其 ScrollController.initialScrollOffset 属性的控制器(ScrollController)。

ScrollController:可用于控制此滚动视图滚动到的位置的对象。

ScrollController.initialScrollOffset:控制初始滚动位置。

Dart 复制代码
  final ScrollController _scrollController = ScrollController(initialScrollOffset: 120);

  child: ListView.builder(
          controller: _scrollController,
          itemBuilder: (context, index) {
            return Card(
              child: Column(
                children: [
                  Container(
                    height: 60,
                    alignment: Alignment.centerLeft,
                    child: Text("Item $index"),
                  ),
                  new Divider()
                ],
              ),
              // child: Container(
              //   height: 60,
              //   alignment: Alignment.centerLeft,
              //   child: Text("Item $index"),
              // ),
            );
          },
          itemCount: 200,
        )

效果如下,打开时会有120的偏移:(Item0上移了)

ScrollController.keepScrollOffset:用于控制滚动视图是否应自动保存和恢复其在 PageStorage 中的滚动位置。每次滚动完成时,使用 PageStorage 保存当前滚动偏移量,如果重新创建此控制器的可滚动项,则恢复它。

ScrollController.offset:用于读取当前滚动位置或更改它。(可以动态获取偏移量)

Dart 复制代码
  final ScrollController _scrollController = ScrollController();


 _scrollController.addListener(() {
      setState(() {
        offset = _scrollController.offset;
        isEnd = _scrollController.position.pixels ==
            _scrollController.position.maxScrollExtent;
      });
    });



 child: ListView.builder(
          controller: _scrollController,
          itemBuilder: (context, index) {
            return Card(
              child: Column(
                children: [
                  Container(
                    height: 60,
                    alignment: Alignment.centerLeft,
                    child: Text("Item $index"),
                  ),
                  new Divider()
                ],
              ),
              // child: Container(
              //   height: 60,
              //   alignment: Alignment.centerLeft,
              //   child: Text("Item $index"),
              // ),
            );
          },
          itemCount: 200,
        )

如下图所示:position:114 表示上滑过程中计算出来的偏移量。

子元素的生命周期

Creation

在布局列表时,可见子元素、状态和渲染对象将基于现有小部件(例如使用默认构造函数时)或延迟提供的小部件(例如使用 ListView.builder 构造函数时)延迟创建。

Destruction

当子元素滚动出视图时,关联的元素子树、状态和渲染对象将被销毁。当滚动回时,列表中相同位置的新子元素将与新元素、状态和渲染对象一起延迟重新创建。

Destruction mitigation

参考:https://api.flutter.dev/flutter/widgets/ListView-class.html?_gl=1*1kk33gn*_ga*NjkxNDYxMjU2LjE3MTMyMzA4MTE.*_ga_04YGWK0175*MTcyNDMzMDgzMi4xNi4xLjE3MjQzMzA5MTcuMC4wLjA.

相关推荐
爱意随风起风止意难平6 小时前
003 flutter初始文件讲解(2)
学习·flutter
每次的天空7 小时前
Android第十一次面试flutter篇
android·flutter·面试
getapi12 小时前
为什么 uni-app 开发的 App 没有明显出现屏幕适配问题Flutter 开发的 App 出现了屏幕适配问题
flutter·uni-app
getapi12 小时前
使用 Flutter 开发 App 时,想要根据 Figma 设计稿开发出响应式 UI 界面
flutter·ui·figma
只可远观12 小时前
Flutter GridView网格组件
flutter
jianleepb14 小时前
2025Flutter(安卓)面试题详解
flutter
90后的晨仔17 小时前
Flutter 中常见的几种页面跳转方式
前端·flutter
90后的晨仔18 小时前
Flutter滚动组件全面解析
前端·flutter
张风捷特烈19 小时前
每日一题 Flutter#2 | 如何理解 Widget 的不可变性
android·flutter·面试
李新_1 天前
我们使用了哪些Flutter 三方库(二)
android·flutter·ios