Flutter 学习之旅(二十) 可滚动控件 ListVi
ListView 可以说是App中最常用的几个控件之一了,先来看一下他的构造参数
ListView({
/// ScrollView 公共参数
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
DragStartBehavior dragStartBehavior = DragStartBehavior.start, ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
///ListView 参数
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
List<Widget> children = const <Widget>[],
int semanticChildCount,
})
这里ScrollView公用的参数在前面已经写了很多次了,这里就不再赘述了,
下面来说一下ListView 新建参数
itemExtent
子条目沿主轴方向的长度,如果主轴方向是垂直的,则itemExtent的长度为item的高度,如果指定itemExtent的高度的话会加快ListView 的构建速度,不用每次填充条目的时候还要计算它的高度
shrinkWrap
表示是否按照子条目的高度来确定ListView 的高度,默认为false,如果在无限高的布局中shrinkWrap必须为true,例如ScrollView 嵌套 ListView 中,shrinkWrap就必须为true
addAutomaticKeepAlives
是否将子条目包裹在AutomaticKeepAlive 中,如果为true,他在移出窗口后也不会被回收,而是被KeepAliveNotification保存,如果想要手动管理KeepAlive状态,必须给false,
addRepaintBoundaries
表示是否将列子条目包裹在RepaintBoundary组件中。当可滚动组件滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效。和addAutomaticKeepAlive一样,如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
我学习flutter的整个过程都记录在里面了
https://www.jianshu.com/c/36554cb4c804
class _TsmListViewPage extends State<TsmListViewPage> {
List<String> list_str;
String endTag;
List<String> page = [
'条目1',
'条目2',
'条目3',
'条目4',
'条目5',
'条目6',
'条目7',
'条目8',
'条目9',
'条目10'
];
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('ListView 学习'),
centerTitle: true,
),
body: getBody(),
);
}
getBody() {
if ((list_str ??= []).length == 0) {
return getEmptyView();
}
return getListBody();
}
getListBody() {
if (list_str.length < 100) {
loadDate();
}
return ListView.separated(
itemCount: list_str.length,
separatorBuilder: (context, index) => Divider(),
itemBuilder: (context, index) {
if (list_str[index] == endTag) {
return Container(
padding: const EdgeInsets.all(16.0),
alignment: Alignment.center,
child: SizedBox(
width: 24.0,
height: 24.0,
child: CircularProgressIndicator(strokeWidth: 2.0)),
);
} else {
return Container(
width: double.infinity,
alignment: Alignment.center,
padding: const EdgeInsets.all(10),
child:inflateText(list_str[index], Colors.blueAccent, 16),
);
}
});
}
loadDate() {
Future.delayed(Duration(seconds: 2)).then((e) {
setState(() {
list_str ??= [];
if(list_str.length==0){
list_str.add(endTag);
}
list_str.insertAll(list_str.length-1, page);
if(list_str.length>100){
list_str.removeAt(list_str.length-1);
list_str.add("没有更多条目了");
}
});
});
}
getEmptyView() {
return Container(
color: Colors.white,
child: Center(
child: GestureDetector(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.adjust),
SizedBox(
height: 10,
),
inflateText('点击刷新', Colors.redAccent, 14),
],
),
onTap: () {
loadDate();
printString("开始刷新");
},
),
),
);
}
}
这里面有个特殊的用法,如果想要实现一个listview有多种条目,可以在build的时候根据index 判断,
然后使用不同的widget,其他的没有什么可以说的了,
我学习flutter的整个过程都记录在里面了
https://www.jianshu.com/c/36554cb4c804
最后附上demo 地址