介紹
線性排列的可滾動(dòng)列表。
核心屬性
ListView({
Key? key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
bool shrinkWrap = false,
EdgeInsetsGeometry? padding,
this.itemExtent,
this.prototypeItem,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double? cacheExtent,
List<Widget> children = const <Widget>[],
int? semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
String? restorationId,
Clip clipBehavior = Clip.hardEdge,
})
- scrollDirection
設(shè)置滾動(dòng)方向,其值有:
enum Axis {
/// 水平方向滾動(dòng),默認(rèn)
horizontal,
/// 豎直方向滾動(dòng)
vertical,
}
- controller
滾動(dòng)控制器。能夠獲取滾動(dòng)相關(guān)信息 - primary
當(dāng)內(nèi)容不足以滾動(dòng)時(shí),是否支持滾動(dòng);true:用來解決listView不滿一頁(yè)無(wú)法觸發(fā)下拉刷新,需要注意這個(gè)時(shí)候不可以設(shè)置controller - physics:控制用戶滾動(dòng)視圖的交互,可以提供邊界回彈特效
- AlwaysScrollableScrollPhysics:列表總是可滾動(dòng)的。在iOS上會(huì)有回彈效果,在android上不會(huì)回彈。那么問題來了,如果primary設(shè)置為false(內(nèi)容不足時(shí)不滾動(dòng)),且 physics設(shè)置為AlwaysScrollableScrollPhysics,列表也是是可以滑動(dòng)的
- PageScrollPhysics:一般是給PageView控件用的滑動(dòng)效果。如果listview設(shè)置的話在滑動(dòng)到末尾時(shí)會(huì)有個(gè)比較大的彈起和回彈
- ClampingScrollPhysics:滾動(dòng)時(shí)沒有回彈效果,同android系統(tǒng)的listview效果
- NeverScrollableScrollPhysics:就算內(nèi)容超過列表范圍也不會(huì)滑動(dòng)
- BouncingScrollPhysics:不論什么平臺(tái)都會(huì)有回彈效果
- shrinkWrap
默認(rèn)false:則高度為滑動(dòng)方向上的最大允許高度;如果在滑動(dòng)方向上沒有設(shè)置約束,則這個(gè)字段必須設(shè)置為true,否則會(huì)報(bào)錯(cuò)。簡(jiǎn)而言之就是父節(jié)點(diǎn)為滑動(dòng)組件的時(shí)候,且滑動(dòng)方向一致需要true,例如:SingleChildScrollView。 - padding
內(nèi)邊距 - itemExtent
指定Item在滑動(dòng)方向上的高度,用來提高滑動(dòng)性能。指定了該屬性后,Item自己定的高度將失效。 - prototypeItem
指定Item在滑動(dòng)方向上的高度為prototypeItem屬性的widget的高度,用來提高滑動(dòng)性能。指定了該屬性后,Item自己定的高度將失效。 - addAutomaticKeepAlives
是否將子控件包裹在AutomaticKeepAlive控件內(nèi)。 - addRepaintBoundaries
是否將子控件包裹在 RepaintBoundary 控件內(nèi)。用于避免列表滾動(dòng)時(shí)的重繪,如果子控件重繪開銷很小時(shí),比如子控件就是個(gè)色塊或簡(jiǎn)短的文字,把這個(gè)字段設(shè)置為false性能會(huì)更好 - cacheExtent
可見區(qū)域的前后會(huì)有一定高度的空間去緩存子控件,當(dāng)滑動(dòng)時(shí)就可以迅速呈現(xiàn) - children
子控件數(shù)組
示例
ListView有四種使用方式:
- ListView()
默認(rèn)構(gòu)造方法,可以在子組件比較少時(shí)使用,因?yàn)椴还茏咏M件是否可見,都會(huì)創(chuàng)建出所有child。
ListView(
children: [
Container(
height: 300,
color: Colors.pink,
child: const Center(child: Text("This is a item1"),),
),
Container(
height: 300,
color: Colors.teal,
child: const Center(child: Text("This is a item2"),),
),
Container(
height: 300,
color: Colors.amber,
child: const Center(child: Text("This is a item3"),),
),
],
);
- ListView.builder()
這種方式屬于懶加載方式,比較常用。傳參數(shù)跟ListView()差不多,區(qū)別是沒有children屬性,代替的是 itemBuilder 和 itemCount
- itemBuilder:IndexedWidgetBuilder Function類型,創(chuàng)建子組件
- itemCount:item數(shù)量
ListView.builder(itemBuilder: (context, index) {
Color? color;
if (index % 2 == 0) {
color = Colors.pink;
} else if (index % 3 == 0) {
color = Colors.teal;
} else if (index % 5 == 0) {
color = Colors.amber;
}
return Container(
height: 100,
color: color,
child: Center(child: Text("This is a item:$index"),),
);
}, itemCount: 50, itemExtent: 200,);
- ListView.separated()
跟ListView.builder()差不多,可以設(shè)置分割線,需要傳一個(gè)separatorBuilder。
ListView.separated(
itemBuilder: (context, index) {
Color? color;
if (index % 2 == 0) {
color = Colors.pink;
} else if (index % 3 == 0) {
color = Colors.teal;
} else if (index % 5 == 0) {
color = Colors.amber;
}
return Container(
height: 100,
color: color,
child: Center(
child: Text("This is a item:$index"),
),
);
},
separatorBuilder: (context, index) {
return const Divider();
},
itemCount: 50,
);
- ListView.custom()
這個(gè)是比較高階的用法了,可以自己去實(shí)現(xiàn)子控件的復(fù)用重繪。這里就不展開說了
-
childrenDelegate:SliverChildDelegate;有兩個(gè)默認(rèn)實(shí)現(xiàn)SliverChildListDelegate,SliverChildBuilderDelegate;方式1實(shí)際上內(nèi)部實(shí)現(xiàn)是SliverChildListDelegate,方式2,3內(nèi)部實(shí)現(xiàn)是SliverChildBuilderDelegate;
效果圖:
