ListView是flutter中线性排列的可滚动的列表部件。ListView 是最常用的滚动小部件。它在滚动方向上一个接一个地显示其子项。在交叉轴上,子项需要填满 ListView。
如果非空,则 itemExtent 会强制子项在滚动方向上具有给定的范围。
如果非空,则prototypeItem 会强制子项在滚动方向上具有与给定小部件相同的范围。 指定 itemExtent 或prototypeItem 比让子项确定自己的范围更有效,因为滚动机制可以利用对子项范围的预知来节省工作,例如当滚动位置发生剧烈变化时。 您不能同时指定 itemExtent 和prototypeItem,只能指定其中一个或不指定其中任何一个。
构建 ListView 有四种选项
1.默认构造函数采用显式 List<Widget> 子项
此构造函数适用于子项数量较少的列表视图,因为构造 List 需要为列表视图中可能显示的每个子项(而不仅仅是实际可见的子项)执行工作。默认 List 方式,是把数据添加到列表中,然后直接添加到 ListView。 Tips: 如果需要设置分割线,使用ListTile.divideTiles。
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,它根据需要构建子项
此构造函数适用于子项数量较多(或无限)的列表视图,因为仅对实际可见的子项调用构建器。
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。
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 直接添加分割线。
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 可以控制用于估计实际不可见的子项大小的算法。
List<String> entries = <String>['C', 'Y', 'Z', 'Y'];class KeepAliveItem extends StatelessWidget {const KeepAliveItem({required Key super.key,required this.data,});final String data;@overrideWidget 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:控制初始滚动位置。
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:用于读取当前滚动位置或更改它。(可以动态获取偏移量)
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.