先看下以下截图 git
flutter
官方demo
flutter_gallery
内copy的部分代码。 首先,首先定义一个列表,代码以下
List<String> items = <String>[
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
];
复制代码
而后,经过上面的定义的列表数据,如今构建ListView
的子Widget数据,代码以下github
Iterable<Widget> listTiles = items
.map<Widget>((String item) => buildListTile(context, item));
Widget buildListTile(BuildContext context, String item) {
Widget secondary = const Text(
'Even more additional list item information appears on line three.',
);
return ListTile(
isThreeLine: true,
leading: ExcludeSemantics(child: CircleAvatar(child: Text(item))),
title: Text('This item represents $item.'),
subtitle: secondary,
trailing: Icon(Icons.info, color: Theme.of(context).disabledColor),
);
}
复制代码
最后,将生成的子Widget数据填充到ListView
内,代码以下redux
ListView(
children: listTiles.toList(),
)
复制代码
以上代码,就能完成最上面截图的效果。下面主要对ListTile
作一下介绍app
ListTile
是Flutter
给咱们准备好的widget提供很是常见的构造和定义方式,包括文字,icon,点击事件,通常是可以知足基本列表需求。async
ListTile({
Key key,
this.leading,
this.title,
this.subtitle,
this.trailing,
this.isThreeLine = false,
this.dense,
this.contentPadding,
this.enabled = true,
this.onTap,
this.onLongPress,
this.selected = false,
})
复制代码
ListTile(
//展现三行
isThreeLine: true,
//前置图标
leading: ExcludeSemantics(child: CircleAvatar(child: Text(item))),
//标题
title: Text('This item represents $item.'),
//副标题
subtitle: secondary,
//后置图标
trailing: Icon(Icons.info, color: Theme.of(context).disabledColor),
)
复制代码
ListView.builder适合列表项比较多(或者无限)的状况,由于只有当子Widget真正显示的时候才会被建立。 将上面列表填充的代码修改成ListView.builder
,代码以下所示ide
ListView.builder(
itemCount: items.length,
itemBuilder: (BuildContext context, int index) {
return buildListTile(context, items[index]);
})
复制代码
运行结果以下图所示 函数
ListView.separated
能够生成列表项之间的分割器,它比ListView.builder多了一个separatorBuilder参数,该参数是一个分割器生成器。 将上面列表填充的代码修改成ListView.separated
,代码以下所示post
ListView.separated(
itemBuilder: (BuildContext context, int index) {
return buildListTile(context, items[index]);
},
separatorBuilder: (BuildContext context, int index) {
return index % 2 == 0 ? divider1 : divider2;
},
itemCount: items.length
)
复制代码
运行结果以下图所示 学习
下面实现首次进入页面,加载数据,下拉能刷新页面数据,上拉能加载更多数据。ui
下拉刷新,用到的是Flutter
自带的RefreshIndicator
Widget,ListView
主要用ListView.builder
进行实现。代码以下所示
RefreshIndicator(
key: refreshIndicatorKey,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (context, index) {
return buildListTile(context, list[index]);
},
),
onRefresh: onRefresh)
复制代码
实现下拉刷新,主要须要实现RefreshIndicator
的onRefresh
属性,代码以下所示
Future<Null> onRefresh() async {
return Future.delayed(Duration(seconds: 2)).then((e) {
list.addAll(items);
setState(() {
//从新构建列表
});
});
}
复制代码
主要实现延迟2s加载数据,在从新刷新列表。 首次进入页面,Loading
状态的实现实现以下面代码所示
void showRefreshLoading() async {
await Future.delayed(const Duration(seconds: 0), () {
refreshIndicatorKey.currentState.show().then((e) {});
return true;
});
}
复制代码
当Loading
完以后会触发RefreshIndicator
的onRefresh
属性,到此,下拉刷新已经实现完毕。 运行效果以下图所示
上拉加载须要监听ListView
的滚动事件,当滚动事件与底部小于50而且有更多数据加载时,才会触发加载更多的逻辑,以下面代码所示
scrollController.addListener(() {
var position = scrollController.position;
// 小于50px时,触发上拉加载;
if (position.maxScrollExtent - position.pixels < 50 &&
!isNoMore) {
loadMore();
}
});
void loadMore() async {
if (!isLoading) {
//刷新加载状态
isLoading = true;
setState(() {});
Future.delayed(Duration(seconds: 2)).then((e) {
list.addAll(items);
//取消加载状态,并提示暂无更多数据
isLoading = false;
isNoMore = true;
setState(() {
//从新构建列表
});
});
}
}
复制代码
视图层的代码,当须要处理加载更多的逻辑时,ListView
的itemCount
属性须要进行加1,用来填充加载更多的视图。以下面代码所示
int getListItemCount() {
int count = list.length;
if (isLoading || isNoMore) {
count += 1;
}
return count;
}
复制代码
ListView
的itemBuilder
属性,加载更多的视图代码以下所示
Widget builderMore() {
return Center(
child: Padding(
padding: EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
isNoMore
? Text("")
: SizedBox(
width: 20.0,
height: 20.0,
child: CircularProgressIndicator(
strokeWidth: 4.0,
valueColor: AlwaysStoppedAnimation(Colors.black)),
),
Padding(
padding: EdgeInsets.symmetric(vertical: 5.0, horizontal: 15.0),
child: Text(
isNoMore ? "没有更多数据" : "加载中...",
style: TextStyle(fontSize: 16.0),
),
),
],
),
),
);
}
复制代码
对RefreshIndicator
代码作以下修改
RefreshIndicator(
key: refreshIndicatorKey,
child: ListView.builder(
controller: scrollController,
itemCount: getListItemCount(),
itemBuilder: (context, index) {
return builderItem(context, index);
},
),
onRefresh: onRefresh)
Widget builderItem(BuildContext context, int index) {
if (index < list.length) {
return buildListTile(context, list[index]);
}
return builderMore();
}
复制代码
运行代码 加载中的效果以下图所示