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.

相关推荐
江上清风山间明月1 天前
Flutter开发的应用页面非常多时如何高效管理路由
android·flutter·路由·页面管理·routes·ongenerateroute
Zsnoin能2 天前
flutter国际化、主题配置、视频播放器UI、扫码功能、水波纹问题
flutter
早起的年轻人2 天前
Flutter CupertinoNavigationBar iOS 风格导航栏的组件
flutter·ios
HappyAcmen2 天前
关于Flutter前端面试题及其答案解析
前端·flutter
coooliang2 天前
Flutter 中的单例模式
javascript·flutter·单例模式
coooliang2 天前
Flutter项目中设置安卓启动页
android·flutter
JIngles1232 天前
flutter将utf-8编码的字节序列转换为中英文字符串
java·javascript·flutter
B.-2 天前
在 Flutter 中实现文件读写
开发语言·学习·flutter·android studio·xcode
freflying11192 天前
使用jenkins构建Android+Flutter项目依赖自动升级带来兼容性问题及Jenkins构建速度慢问题解决
android·flutter·jenkins
机器瓦力3 天前
Flutter应用开发:对象存储管理图片
flutter