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
和我们OC
UItableView
的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
待更新...