1 ListView 简介
ListView 是一个列表组件, 继承于 BoxScrollView, 是可以垂直或者水平滑动的,
ListView的继承链:
ListView->BoxScrollView->ScrollView->StatelessWidget
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: const Text('ListView Demo'),),
body: Center(
child: createListView(),
),
),
);
}
}
2 ListView 构造
2.1 ListView 同名构造函数
我们用同名构造函数来写一个简单的列表, 需要传入一个 Widget 数组, 数组中的每一条 item 都是一个 Widget, 这种方法适合静态页面, 数据不发生变化的情况; 同时可以设置一个内边距, 这个内边距是 ListView 内部的, 而不是每一条 item 的,
Widget createListView() {
return Container(
color: Colors.yellow,
child: ListView(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.all(10),
children: [
Container(
color: Colors.grey,
width: 100,
height: 100,
child: const Text(
'C 1',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.green,
width: 100,
height: 100,
child: const Text(
'C 2',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.blue,
width: 100,
height: 100,
child: const Text(
'C 3',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.grey,
width: 100,
height: 100,
child: const Text(
'C 4',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.green,
width: 100,
height: 100,
child: const Text(
'C 5',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.blue,
width: 100,
height: 100,
child: const Text(
'C 6',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.grey,
width: 100,
height: 100,
child: const Text(
'C 7',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.green,
width: 100,
height: 100,
child: const Text(
'C 8',
style: TextStyle(fontSize: 20,),
),
),
Container(
color: Colors.blue,
width: 100,
height: 100,
child: const Text(
'C 9',
style: TextStyle(fontSize: 20,),
),
),
],
),
);
}
- 垂直滚动效果, 此时
item设置宽度是不生效的, 只有高度有效.
- 水平滚动效果, 此时
item设置高度是不生效的, 只有宽度生效.
2.1 ListView.builder
builder 这个构造函数, 有一个必传参数 itemBuilder, 这个参数的类型是 IndexedWidgetBuilder 这个类型是一个函数; 另外一个常用参数是 itemCount, 就是列表中 cell 的数量, 如果不传会显示无数个.
- IndexedWidgetBuilder
IndexedWidgetBuilder和我们OCUItableView的cellForRow方法非常像, 传入一个context, 一个下标index, 函数返回一个Widget, 列表根据数量循环调用.
typedef IndexedWidgetBuilder = Widget Function(BuildContext context, int index);
我们按照 IndexedWidgetBuilder 这个类型, 自定义一个函数 Widget cellForRow(BuildContext context, int index), 作为 itemBuilder 参数传入 builder, 数量来个20, 来看一下效果, 这个就只展示垂直滚动的, 水平滚动就不展示了, 只是方向不同而已.
Widget createListView() {
return Container(
color: Colors.white,
child: ListView.builder(
itemCount: 20,
itemBuilder: cellForRow,
),
);
}
// 自定义一个 cell
Widget cellForRow(BuildContext context, int index) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
color: Colors.grey,
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
width: 120,
height: 170,
child: Image.asset(
'images/icon_img.png', //200 * 300
),
),
Container(
margin: const EdgeInsets.only(right: 10),
color: Colors.blue,
child: const SizedBox(
width: 50,
height: 80,
)
)
],
),
Container(
height: 1,
color: Colors.yellow,
child: Row(
children: [
Container(
width: 10,
color: Colors.white,
),
]
),
)
],
);
}
2.2 ListView.separated
separated 是一个带分割线的列表, 可以单独设置分割线, 在最后一个 cell 下边是没有的, 也就是说分割线的数量比 cell 数量少 1, 除了 itemBuilder 是必传参数, 还有 itemCount 和 separatorBuilder 也是必传参数, separatorBuilder 与 itemBuilder 类型相同.
Widget createListView() {
return Container(
color: Colors.white,
child: ListView.separated(
itemCount: 20,
itemBuilder: cellForRow,
separatorBuilder: separatorForRow,
),
);
}
// 自定义分割线
Widget separatorForRow(BuildContext context, int index) {
return Container(
height: 2,
color: Colors.red,
);
}
Widget cellForRow(BuildContext context, int index) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
color: Colors.grey,
padding: const EdgeInsets.fromLTRB(10, 10, 10, 10),
width: 120,
height: 170,
child: Image.asset(
'images/icon_img.png', //200 * 300
),
),
Container(
margin: const EdgeInsets.only(right: 10),
color: Colors.blue,
child: const SizedBox(
width: 50,
height: 80,
)
)
],
);
}
2.3 ListView.custom
待更新...