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, 本文版權屬於再惠研發團隊,歡迎轉載,轉載請保留出處。函數