flutter中常用的列表組件爲ListView、GridView和SliverList,本文將3種組件實現步驟和多種實現方式做個講解。
一、ListView
能夠實現靜態加載和動態加載。所謂的靜態加載就是需要設置好Listview所加載的子view,數量已定。所謂的動態加載就是子view數量不定。
1、靜態加載
(1)源碼屬性:
有幾個比較重要的屬性:
- scrollDirection:滾動方向
- itemExtent :決定子view的高度或寬度。
- children :子view。
(2)使用:
class ListViewWidget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('ListViewWidget1'),
),
body: ListView(
scrollDirection: Axis.vertical,
itemExtent: 80, //限制每一項的高度或寬度,即使子view設置了高度。
children: <Widget>[
Container(
height: 50,
color: Colors.red,
),
Container(
height: 50,
color: Colors.green,
),
Container(
height: 50,
color: Colors.blue,
),
],
),
);
}
}
在children中給指定要加載的子view。注意這裏即使設置了子view的高度爲50,由於itemExtent設置爲80。所以子view的高度爲80。
2、動態加載–ListView.builder
(1)源碼屬性:
有幾個比較重要的屬性:
- itemBuilder:用於加載子view
- itemCount:限制子view的個數。
(2)使用:
class ListViewWidget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('ListViewWidget2'),
),
body: ListView.builder(
reverse: true,
itemBuilder: (context, index) {//index爲子view下標。
return index % 2 == 0
? Container(
height: 50,
color: Colors.red,
)
: Container(
height: 50,
color: Colors.green,
);
},
itemCount: 100, //顯示條目數量,不指定顯示無限數量
itemExtent: 30,
),
);
}
}
現象就是兩個色塊交替顯示,總共100條。
3、動態加載–ListView.separated
(1)源碼屬性:
有幾個比較重要的屬性:
- itemBuilder:用於加載子view
- itemCount:限制子view的個數。
- separatorBuilder:用於加載分割每個子view間的分割線。
(2)使用:
class ListViewWidget3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('ListViewWidget2'),
),
body: ListView.separated(
itemBuilder: (context, index) {
//item
return index % 2 == 0
? Container(
height: 50,
color: Colors.red,
)
: Container(
height: 50,
color: Colors.green,
);
},
separatorBuilder: (context, index) {
//分割線
return Divider(
height: 5,
color: Colors.black,
thickness: 5,
);
},
itemCount: 100));
}
}
現象就是兩個色塊交替顯示,總共100條。每個子view之間有5px的黑色分割線。
4、動態加載–實現ListView分頁加載
(1)先上代碼吧,後面詳解:
class ListViewWidget4 extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return ListViewWidget4State();
}
}
class ListViewWidget4State extends State<ListViewWidget4> {
List<String> _datas = <String>[''];
//初始化數據
void _initData() {
//模擬網絡加載,每次生成20條數據
Future.delayed(Duration(milliseconds: 100), () {
_datas.insertAll(_datas.length - 1,
generateWordPairs().take(20).map((e) => e.asPascalCase).toList());
//刷新數據
setState(() {});
});
}
@override
void initState() {
super.initState();
//初始化數據
_initData();
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(title: Text('分頁listView')),
body: ListView.builder(
itemBuilder: (context, index) {
if (_datas.length - 1 == index) {
if (_datas.length < 100) {
//最多加載100條
_initData();
return Container(
width: 10,
height: 10,
child: CircularProgressIndicator(),
);
} else {
return Center(
child: Container(
height: 20,
color: Colors.red,
child: Text(
('沒有更多數據了'),
),
));
}
}
return ListTile(
//數據顯示
title: Text(_datas[index]),
);
},
itemCount: _datas.length, //列表長度
),
);
}
}
由於我們需要刷新動態刷新列表數據的,所以這裏使用StatefulWidget。通過_initData()方法來模擬網絡加載,每次加載20條,通過第三方隨機生成20個字符串。itemBuilder中限制最多加載100條,並且不足100條,每次下拉到最後一項都會再次生成20個字符串。
(2)效果:
二、GridView
1、靜態加載–GridView
(1)源碼屬性:
有幾個比較重要的屬性:
- gridDelegate:用於控制每一行或每一列顯示的子view個數,以及子view間距
- children : 子view列表
(2)使用:
class GridViewWidget1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('GridViewWidget1'),
),
body: GridView(
padding: EdgeInsets.all(10), //外邊距
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3, //控制每一行顯示的個數,子view的寬度自動計算
mainAxisSpacing: 5, //主軸方向的child間距
crossAxisSpacing: 5, //垂直軸方向的child間距
childAspectRatio: 2 //控制寬高比,此時表示高度爲寬度的一半
),
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
],
),
);
}
}
現象就是每一行顯示3個色塊,總共顯示2行,子view之間橫向和縱向間距爲5,注意 childAspectRatio 控制子view的顯示寬高比。
2、靜態加載–GridView.count
這種方式能夠實現和上述方式一樣的效果。
(1)源碼屬性:
注意這裏的幾個屬性mainAxisSpacing、crossAxisSpacing、childAspectRatio就是之前方式gridDelegate的屬性。
(2)使用:
class GridViewWidget2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('GridViewWidget3'),
),
body: GridView.count(
crossAxisCount: 3,
mainAxisSpacing: 5,
//主軸方向的child間距
crossAxisSpacing: 5,
//垂直軸方向的child間距
childAspectRatio: 2,
//子view
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
],
),
);
}
}
3、靜態加載–GridView.extent
可以實現不指定每一行或每一列顯示的個數,自動適配個數。
(1)源碼屬性:
重要屬性:
- maxCrossAxisExtent:控制每一行顯示多少個子view
(2)使用:
class GridViewWidget4 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('GridViewWidget4'),
),
body:
GridView.extent(maxCrossAxisExtent: 100, //指定每個子view的最大寬度,顯示個數根據屏幕寬度而定
children: <Widget>[
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.pink,
),
Container(
color: Colors.black,
),
Container(
color: Colors.yellow,
),
]),
);
}
}
4、動態加載–GridView.builder
(1)源碼屬性:
重要屬性:
- gridDelegate:用於控制每一行或每一列顯示的子view個數,以及子view間距
- itemBuilder:動態加載每一個子view
- itemCount:指定顯示子view的個數
(2)使用:
class GridViewWidget3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: AppBar(
title: Text('GridViewWidget3'),
),
body: GridView.builder(
itemCount: 11, //子view顯示的個數
gridDelegate: //設置每一行顯示3個
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (context, index) {
//加載每一個子view
return index % 2 == 0
? Container(
color: Colors.red,
)
: Container(
color: Colors.blue,
);
}));
}
}
三、SliverList–SliverFixedExtentList
這裏只講解SliverFixedExtentList。我們用它配合 SliverAppBar 實現android中 CollapsingToolbarLayout 的效果。
(1)使用:
class SliverListWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('SliverAppBar'),
backgroundColor: Colors.pinkAccent,
expandedHeight: 200,
floating: true,//floating 和snap同時設置爲true,下拉會like顯示flexibleSpace內容。
snap: true,
pinned: true,//appBar不會消失,一直在標題欄
flexibleSpace: FlexibleSpaceBar(//圖片
background: Image.asset(
"assets/images/lock_bg.png",
fit: BoxFit.cover,
),
),
),
SliverFixedExtentList(//子view展示
itemExtent: 150,
delegate: SliverChildListDelegate.fixed([
Container(
color: Colors.red,
),
Container(
color: Colors.green,
),
Container(
color: Colors.blue,
),
Container(
color: Colors.pink,
),
Container(
color: Colors.black,
),
Container(
color: Colors.yellow,
),
]))
],
),
);
}
}
(2)效果: