文章目录
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),
);
}
);
一般列表中我们都会有添加 上拉加载 和 下拉刷新 的功能,有的页面布局还会增加头部和尾部。
扫描二维码关注公众号,回复:
10017403 查看本文章
上拉加载 的功能在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,
),
),
],
),
),
),
);
}
}
完~