ListView(
children: <Widget>[
ListTile(title: Text("普通ListView")),
ListTile(
title: Text("ListView.build"),
onTap: () {
Navigator.pushNamed(context, '/listview_build');
}),
],
)
复制代码
适用场景:已知有限个Item的状况下android
ListView.builder(
itemBuilder: (context, index) => Text("Item $index"),
itemCount: 100)
复制代码
适用场景:长列表时采用builder模式,能提升性能。不是把全部子控件都构造出来,而是在控件viewport加上头尾的cacheExtent这个范围内的子Item才会被构造。在构造时传递一个builder,按需加载是一个惯用模式,能提升加载性能。git
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))
复制代码
ListView.separated(
itemBuilder: (context, index) {
return Text("Item $index");
},
separatorBuilder: (context, index) {
return Container(
color: Colors.grey,
height: 3,
);
},
itemCount: 100)
复制代码
适用场景:列表中须要分割线时,能够自定义复杂的分割线github
须要自定义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模式bash
ListView最为app最多见的控件之一,掌握它的用法很是重要。本文主要给Flutter萌新们介绍ListView的几种构造方式和参数含义,视图控件的学习应多动手写写demo,真实体会各个参数的效果。app
最后附上demo以供参考。ide
@akindone, 本文版权属于再惠研发团队,欢迎转载,转载请保留出处。函数