flutter 实现列表的几种方法,ListView简单实现列表的下拉刷新、动态生成
flutter 实现列表(ListView)的几种方法,简单实现列表的下拉刷新、动态生成
列表在软件上是一个最常用的部分,几乎所有软件APP都离不开列表,比如聊天软件有好友列表,购物软件有商品列表,音乐播放软件有音乐列表,所以具备列表实现的知识很有必要。在flutter中列表相关的组件有很多,我们现在就用ListView来实现一个列表吧。
ListView
ListView是最常用的可滚动组件之一,它可以沿一个方向线性排布所有子组件,并且它也支持列表项懒加载(在需要时才会创建)。下边是ListView的默认构造函数。默认构造函数有一个children参数,它接受一个Widget列表(List)。这种方式适合只有少量的子组件数量已知且比较少的情况,反之则应该使用ListView.builder 按需动态构建列表项。
ListView({
...
//可滚动widget公共参数
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
EdgeInsetsGeometry? padding,
//ListView各个构造函数的共同参数
double? itemExtent,
Widget? prototypeItem, //列表项原型,后面解释
bool shrinkWrap = false,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double? cacheExtent, // 预渲染区域长度
//子widget列表
List<Widget> children = const <Widget>[],
})
ListView.builder
ListView.builder适合列表项比较多或者列表项不确定的情况。下边是结合ListTile生成10个列表的例子。ListView.builder 接受两个参数:itemCount: int
,itemBuilder: @required IndexedWidgetBuilder itemBuilder,
itemCount
这个参数声明了 list 的长度,这个值表明 ListView 中会存在多少个 item 子项。从 itemBuilder 的表面含以上也能够知道它是用来构造每个子项组件的,它的类型是IndexedWidgetBuilder,其实是一个方法,接受 context 和 index 两个参数。context:构造的上下文,index: 当前索引。
class List extends StatelessWidget {
const List({super.key});
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 20,
itemExtent: 50.0, //强制高度为50.0
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
});
}
}
ListTile
ListTile 通常用于在 Flutter 中填充 ListView,我们可以对ListTile设置来美化上边实现的列表,可以通过subtitle添加副标题,通过leading设置头像图标,通过trailing设置尾部图标,selected为选中状态,默认为 false。
class List extends StatefulWidget {
const List({super.key});
@override
State<List> createState() => _ListState();
}
class _ListState extends State<List> {
// bool selectedtrue=false;
@override
Widget build(BuildContext context) {
return ListView.builder(
itemCount: 20,
itemExtent: 60.0, //强制高度为50.0
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: const Icon(Icons.people, color: Colors.blue),
title: Text(
"$index 列表标题",
style: TextStyle(color: Colors.blue),
),
//subtitle:Text("$index 列表副标题") ,
trailing: const Icon(
Icons.keyboard_arrow_right,
color: Colors.blue,
),
//selected: selectedtrue,
hoverColor: Colors.blue,
focusColor: Colors.blue,
// tileColor: Colors.yellow,
autofocus: true,
onTap: () {
print("$index");
setState(() {
//selectedtrue=true;
});
},
);
});
}
}
ListView.separated 带分隔符的列表
当我们想要列表有分割线的时候可以用ListView.separated, ListView.separated与 ListView.builder 的唯一不同就是多了个separatorBuilder,通过接受 BuildContext context, int index 两个参数,再返回一个 Widget,其他的和 ListView.builder 的使用方法一样。separatorBuilder 也可以使用别的 Widget当做分隔符,图片、图标都可以:
class List extends StatefulWidget {
const List({super.key});
@override
State<List> createState() => _ListState();
}
class _ListState extends State<List> {
// bool selectedtrue=false;
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: 20,
// itemExtent: 60.0, //强制高度为50.0
separatorBuilder: (BuildContext context, int index) {
return const Divider(
color: Colors.red,
);
},
itemBuilder: (BuildContext context, int index) {
return ListTile(
leading: const Icon(Icons.people, color: Colors.blue),
title: Text(
"$index 列表标题",
style: TextStyle(color: Colors.blue),
),
//subtitle:Text("$index 列表副标题") ,
trailing: const Icon(
Icons.keyboard_arrow_right,
color: Colors.blue,
),
//selected: selectedtrue,
hoverColor: Colors.blue,
focusColor: Colors.blue,
// tileColor: Colors.yellow,
autofocus: true,
onTap: () {
print("$index");
setState(() {
//selectedtrue=true;
});
},
);
});
}
}
动态生成长列表
一般情况下,我们需要根据数据来生成列表,现在就模仿实现一下。首先哦们创建一个列表来存放我们的源数据,命名为listData,在listData放入标题、图标、颜色,这样我们可以生成不同图标、不同标题、不同颜色的列表。如果有其他需求,比如定制副标题等需求,修改listData里面的元素就可以了。列表使用ListView.separated生成,有分隔符看起来清楚一点,当然分隔元素也可以换成其他的组件。
class Listbuildtest extends StatefulWidget {
const Listbuildtest({super.key});
@override
State<Listbuildtest> createState() => _ListbuildtestState();
}
class _ListbuildtestState extends State<Listbuildtest> {
// bool selectedtrue=false;
void funcfor() {
print("ndex");
}
/* @override
void initState() {//重写初始化函数
for (var i = 0; i < 10; i++) {
//sleep(const Duration(seconds: 5));
print(i.toString());
print("initState*************");
super.initState();
}
}*/
List listData = [//数据列表
{
'title': 'Python 创作季,秀出你的文章',
'icon': Icons.people,
'color': Colors.blue,
},
{
'title': 'Golang 创作季,秀出你的文章',
'icon': Icons.gamepad_rounded,
'color': Colors.orange,
},
{
'title': 'Dart 创作季,秀出你的文章',
'icon': Icons.network_cell,
'color': Colors.green,
},
{
'title': 'C/C++ 创作季,秀出你的文章',
'icon': Icons.cabin,
'color': Colors.pink,
},
{
'title': 'java 创作季,秀出你的文章',
'icon': Icons.access_alarm_rounded,
'color': Colors.purple,
}
];
@override
Widget build(BuildContext context) {
return ListView.separated(
itemCount: listData.length,
// itemExtent: 60.0, //强制高度为50.0
separatorBuilder: (BuildContext context, int index) {
return const Divider(
color: Colors.red,
);
},
itemBuilder: buildlist);
}
Widget buildlist(BuildContext context, int index) {
return ListTile(
leading: Icon(listData[index]['icon'], color: listData[index]['color'],),
title: Text(
listData[index]['title'],
style: TextStyle( color: listData[index]['color'],),
),
//subtitle:Text("$index 列表副标题") ,
trailing: Icon(
Icons.keyboard_arrow_right,
color: listData[index]['color'],
),
//selected: selectedtrue,
// hoverColor: Colors.blue,
//focusColor: Colors.blue,
// tileColor: Colors.yellow,
autofocus: true,
onTap: () {
funcfor();
print("$index");
setState(() {
//selectedtrue=true;
});
},
);
}
}
列表下拉刷新
RefreshIndicator是Material风格的下拉刷新组件,我们直接使用RefreshIndicator嵌套list组件就可以了,每次刷新我们添加一列PHP。RefreshIndicator的child和onRefresh是必须要实现的。在下触发下拉事件后调用setState改变组件状态,实现界面刷新。
class Listbuildtest extends StatefulWidget {
const Listbuildtest({super.key});
@override
State<Listbuildtest> createState() => _ListbuildtestState();
}
class _ListbuildtestState extends State<Listbuildtest> {
// bool selectedtrue=false;
void funcfor() {
print("ndex");
}
/* @override
void initState() {//重写初始化函数
for (var i = 0; i < 10; i++) {
//sleep(const Duration(seconds: 5));
print(i.toString());
print("initState*************");
super.initState();
}
}*/
List listData = [
//数据列表
{
'title': 'Python 创作季,秀出你的文章',
'icon': Icons.people,
'color': Colors.blue,
},
{
'title': 'Golang 创作季,秀出你的文章',
'icon': Icons.gamepad_rounded,
'color': Colors.orange,
},
{
'title': 'Dart 创作季,秀出你的文章',
'icon': Icons.network_cell,
'color': Colors.green,
},
{
'title': 'C/C++ 创作季,秀出你的文章',
'icon': Icons.cabin,
'color': Colors.pink,
},
{
'title': 'java 创作季,秀出你的文章',
'icon': Icons.access_alarm_rounded,
'color': Colors.purple,
}
];
@override
Widget build(BuildContext context) {
return RefreshIndicator(//下拉刷新组件
onRefresh: () async {
setState(() {
print("下拉刷新");
listData.add(//每次刷新对listdata添加一个元素
{
'title': 'PHP 创作季,秀出你的文章',
'icon': Icons.pages,
'color': Colors.red,
},
);
});
},
child: ListView.separated(
itemCount: listData.length,
// itemExtent: 60.0, //强制高度为50.0
separatorBuilder: (BuildContext context, int index) {
return const Divider(
color: Colors.red,
);
},
itemBuilder: buildlist),
);
}
Widget buildlist(BuildContext context, int index) {
return ListTile(
leading: Icon(//头部图标
listData[index]['icon'],
color: listData[index]['color'],
),
title: Text(//标题
listData[index]['title'],
style: TextStyle(
color: listData[index]['color'],
),
),
//subtitle:Text("$index 列表副标题") ,
trailing: Icon(//尾部图标
Icons.keyboard_arrow_right,
color: listData[index]['color'],
),
//selected: selectedtrue,
// hoverColor: Colors.blue,
//focusColor: Colors.blue,
// tileColor: Colors.yellow,
autofocus: true,//自动聚焦
onTap: () {//点击事件
funcfor();
print("$index");
setState(() {
//selectedtrue=true;
});
},
);
}
}
总结
列表的实现就先到这里,实际使用的时候肯定需要更多的知识和技巧,这些远远不够。本来想实现列表数据定时自动更新的,但是奈何查了半天没找到方法,暂时先放弃了吧。
转载自:https://juejin.cn/post/7240730470974455867