Flutter ListView 用法详解
ListView的4种构造方式
默认构造函数(传入 List children)
ListView( children:
适用场景:已知有限个Item的情况下
builder
ListView.builder( itemBuilder: (context, index) => Text("Item $index"), itemCount: 100) 复制代码
适用场景:长列表时采用builder模式,能提高性能。不是把所有子控件都构造出来,而是在控件viewport加上头尾的cacheExtent这个范围内的子Item才会被构造。在构造时传递一个builder,按需加载是一个惯用模式,能提高加载性能。
构造多种样式的Item
abstract class ListItem {} class HeadingItem implements ListItem { final String heading; HeadingItem(this.heading); } class MessageItem implements ListItem { final String sender; final String body; MessageItem(this.sender, this.body); } ListView.builder( itemBuilder: (context, index) { final item = items[index]; if (item is HeadingItem) { return ListTile( title: Text( item.heading, style: Theme.of(context).textTheme.headline, ), ); } else if (item is MessageItem) { return ListTile( title: Text(item.sender), subtitle: Text(item.body), ); } }, itemCount: items.length)) 复制代码
separated
ListView.separated( itemBuilder: (context, index) { return Text("Item $index"); }, separatorBuilder: (context, index) { return Container( color: Colors.grey, height: 3, ); }, itemCount: 100) 复制代码
适用场景:列表中需要分割线时,可以自定义复杂的分割线
custom
需要自定义SliverChildDelegate,各方法含义如下:
ListView.custom(childrenDelegate: CustomSliverChildDelegate()) class CustomSliverChildDelegate extends SliverChildDelegate { /// 根据index构造child @override Widget build(BuildContext context, int index) { // KeepAlive将把所有子控件加入到cache,已输入的TextField文字不会因滚动消失 // 仅用于演示 return KeepAlive( keepAlive: true, child: TextField(decoration: InputDecoration(hintText: '请输入'))); } /// 决定提供新的childDelegate时是否需要重新build。在调用此方法前会做类型检查,不同类型时才会调用此方法,所以一般返回true。 @override bool shouldRebuild(SliverChildDelegate oldDelegate) { return true; } /// 提高children的count,当无法精确知道时返回null。 /// 当 build 返回 null时,它也将需要返回一个非null值 @override int get estimatedChildCount => 100; /// 预计最大可滑动高度,如果设置的过小会导致部分child不可见,设置报错 @override double estimateMaxScrollOffset(int firstIndex, int lastIndex, double leadingScrollOffset, double trailingScrollOffset) { return 2500; } /// 完成layout后的回调,可以通过该方法获已完成布局的视图树包括哪些子控件 @override void didFinishLayout(int firstIndex, int lastIndex) { print('didFinishLayout firstIndex=$firstIndex firstIndex=$lastIndex'); } } 复制代码
适用场景:上面几种模式基本可以满足业务需求,如果你还想做一些其它设置(如列表的最大滚动范围)或获取滑动时每次布局的子Item范围,可以尝试custom模式
ListView属性含义
ListView的属性
继承自父控件 BoxScrollView 的属性
继承自 ScrollView 的属性
用于构造SliverChildListDelegate的属性
最后
ListView最为app最常见的控件之一,掌握它的用法非常重要。本文主要给Flutter萌新们介绍ListView的几种构造方式和参数含义,视图控件的学习应多动手写写demo,真实体会各个参数的效果。
最后附上demo以供参考。
@akindone, 本文版权属于再惠研发团队,欢迎转载,转载请保留出处。
https://juejin.im/post/5cb1c9d5f265da037371777f