文章目錄
ListView、ListView.builder
這是ListView
的兩個構造函數,ListView
構造函數在列表佈局少的時候使用,ListView.builder
在渲染列表數據多的時候有優勢。
ListView({
Key key,
Axis scrollDirection = Axis.vertical,//設置滑動方向 Axis.horizontal 水平 默認 Axis.vertical 垂直
bool reverse = false,//是否倒序顯示 默認正序 false 倒序true
ScrollController controller,//滑動監聽
bool primary,//false,如果內容不足,則用戶無法滾動 而如果[primary]爲true,它們總是可以嘗試滾動。
ScrollPhysics physics,//列表滾動至邊緣後繼續拖動的物理效果
bool shrinkWrap = false,//child 高度會適配 item填充的內容的高度,
EdgeInsetsGeometry padding,// 列表內邊距
this.itemExtent,//確定每一個item的高度 會讓item加載更加高效
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,//cacheExtent 設置預加載的區域
List<Widget> children = const <Widget>[],// 列表內容
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
})
ListView.builder 的構造函數基本和 ListView 一致,僅多了個字段 int itemCount, 表示列表數據的數量
ListView 使用
Widget _buildListView() {
return ListView(
scrollDirection: Axis.horizontal,
itemExtent: 140, //item延展尺寸(寬度)
children: [
//設置ListTile組件的標題與圖標
ListTile(leading: Icon(Icons.map), title: Text('Map')),
ListTile(leading: Icon(Icons.mail), title: Text('Mail')),
ListTile(leading: Icon(Icons.message), title: Text('Message')),
]
);
}
ListView.builder 使用
ListView.builder(
itemCount: 100,// 100 條數據
itemExtent: 50.0,// 每條數據的高度是50
itemBuilder: (BuildContext context, int index) {
// 每條數據使用 ListTile 渲染
return ListTile(title: Text("$index"));
}
);
ListTile
ListTile
是Flutter
提供的widget
,通過查看參數去了解這個widget
能實現哪些功能。
const ListTile({
Key key,
this.leading,// item 前置圖標
this.title, // item 標題
this.subtitle,// item 副標題
this.trailing,// item 後置圖標
this.isThreeLine = false,// item 是否三行顯示
this.dense,
this.contentPadding,// item 內容內邊距
this.enabled = true,// item 是否可用
this.onTap,// item onTap 點擊事件
this.onLongPress,// item onLongPress 長按事件
this.selected = false,// item 是否選中狀態
})
僞代碼如下:
ListView.builder(
itemCount: 100,
itemExtent: 50.0,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("$index"),
subtitle: Text("subtitle $index"),
leading: Icon(Icons.favorite),
trailing: Icon(Icons.delete),
);
}
);
ListView.separated 分割線
在列表中經常會增加分割線來區分每一個 Item
區域,在Flutter
中也提供了ListView.separated
構造方法實現。
效果圖:分割線高度爲5 ,且 index 爲偶數, 創建綠色分割線,index爲奇數, 則創建紅色分割線
ListView.separated(
itemCount: 100,
//分割器構造器,高度爲5 ,index 爲偶數, 創建綠色分割線, index爲奇數, 則創建紅色分割線
separatorBuilder: (BuildContext context, int index){
return index %2 == 0 ? Divider(thickness:5.0, color: Colors.green) : Divider(thickness:5.0, color: Colors.red);
},
//列表項構造器
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("$index"),
subtitle: Text("subtitle $index"),
leading: Icon(Icons.favorite),
trailing: Icon(Icons.delete),
);
}
);
一般列表中我們都會有添加 上拉加載 和 下拉刷新 的功能,有的頁面佈局還會增加頭部和尾部。
上拉加載 的功能在ListView
可以通過監聽列表滑動來實現。
下拉刷新的功能可以結合RefreshIndicator
這個組件來實現。
頭部和尾部的功能主要是通過判斷ListView
中item
的位置來動態添加widget
,具體可參考這篇文章Flutter 之列表和頭部 (ListView + Header),或者使用CustomScrollView
組件實現。
第三方庫推薦
下面僅使用flutter_easyrefresh
做示例。
上下拉加載數據
- 引入該庫:
dependencies:
flutter_easyrefresh: ^2.0.9
- 使用例子
class EasyRefreshPage extends StatefulWidget {
@override
_EasyRefreshPageState createState() {
return _EasyRefreshPageState();
}
}
class _EasyRefreshPageState extends State<EasyRefreshPage> {
EasyRefreshController _controller;
// 條目總數
int _count = 20;
// 數據已全部加載完成
bool _enableControlFinish = false;
@override
void initState() {
super.initState();
_controller = EasyRefreshController();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('上拉加載、下拉刷新'),
),
body: Center(
child: Container(
child: EasyRefresh.custom(
controller: _controller,
onRefresh:() async {
await Future.delayed(Duration(milliseconds: 200), () {
if (mounted) {
setState(() {
_count = 20;
});
}
});
},
onLoad: () async {
await Future.delayed(Duration(milliseconds: 200), () {
if (mounted) {
setState(() {
_count += 20;
});
// 數據全部加載完成
if (!_enableControlFinish) {
_controller.finishLoad(noMore: _count >= 40);
}
}
});
},
slivers: <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return ListTile(
title: Text('$index'),
);
},
childCount: _count,
),
),
],
),
),
),
);
}
}
完~