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.

相关推荐
lqj_本人2 小时前
鸿蒙next选择 Flutter 开发跨平台应用的原因
flutter·华为·harmonyos
lqj_本人5 小时前
Flutter&鸿蒙next 状态管理框架对比分析
flutter·华为·harmonyos
起司锅仔9 小时前
Flutter启动流程(2)
flutter
hello world smile12 小时前
最全的Flutter中pubspec.yaml及其yaml 语法的使用说明
android·前端·javascript·flutter·dart·yaml·pubspec.yaml
lqj_本人12 小时前
Flutter 的 Widget 概述与常用 Widgets 与鸿蒙 Next 的对比
flutter·harmonyos
iFlyCai12 小时前
极简实现酷炫动效:Flutter隐式动画指南第二篇之一些酷炫的隐式动画效果
flutter
lqj_本人12 小时前
Flutter&鸿蒙next 中使用 MobX 进行状态管理
flutter·华为·harmonyos
lqj_本人13 小时前
Flutter&鸿蒙next 中的 setState 使用场景与最佳实践
flutter·华为·harmonyos
hello world smile14 小时前
Flutter常用命令整理
android·flutter·移动开发·android studio·安卓
lqj_本人17 小时前
Flutter&鸿蒙next 中的 Expanded 和 Flexible 使用技巧详解
flutter·harmonyos