核心功能
用于显示可滚动的线性列表(垂直/水平)
支持懒加载 (builder
系列)和静态列表 (children
)
内置滚动物理效果(弹性和边界效果)
四种构造方法
ListView():一次性构建所有子项
ListView.builder():按需构建子项,性能最优
ListView.separated():自动添加分隔组件
ListView.custom():使用 SliverChildDelegate
ListView的基础列表
Dart
ListView.builder(
itemCount: data.length,
itemBuilder: (ctx, index) {
return ListTile(
title: Text(data[index].title),
subtitle: Text(data[index].subtitle),
);
},
)
构建列表的数据流
①初始化列表数据
②ListView.builder
初始化
③读取 itemCount: users.length
(值为10)
④框架传入当前的 context
和 index
⑤通过 users[index]
获取对应数据
⑥返回构建好的 Card
Widget
当用户点击列表时
①框架检测滚动位置变化
②动态计算新的 index
范围(如滚动后需要显示index 2-5)
③销毁已离开屏幕的列表项(如index 0-1)
④调用 itemBuilder
构建新进入屏幕的项(如index 4-5)
当用户点击列表项时
①触发点击事件
②获取当前 context
和 user.name
③创建并显示SnackBar
④点击"关闭"按钮时销毁SnackBar
代码实例
main.dart
Dart
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: const MyHomePage(title: '水果用户列表'),
);
}
}
//列表项的类
class User {
final String name;
final String email;
final String imageAsset; // 存储本地图片路径
//构造函数
User({
required this.name,
required this.email,
required this.imageAsset,
});
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
// 子项数据,每个用户关联不同的本地图片
final List<User> users = [
User(
name: "苹果用户",
email: "apple@example.com",
imageAsset: 'assets/images/apple.png',
),
User(
name: "香蕉用户",
email: "banana@example.com",
imageAsset: 'assets/images/banana.png',
),
User(
name: "樱桃用户",
email: "cherry@example.com",
imageAsset: 'assets/images/cherry.png',
),
User(
name: "芒果用户",
email: "mango@example.com",
imageAsset: 'assets/images/mango.png',
),
User(
name: "菠萝用户",
email: "pineapple@example.com",
imageAsset: 'assets/images/pineapple.png',
),
User(
name: "苹果用户",
email: "apple@example.com",
imageAsset: 'assets/images/apple.png',
),
User(
name: "香蕉用户",
email: "banana@example.com",
imageAsset: 'assets/images/banana.png',
),
User(
name: "樱桃用户",
email: "cherry@example.com",
imageAsset: 'assets/images/cherry.png',
),
User(
name: "芒果用户",
email: "mango@example.com",
imageAsset: 'assets/images/mango.png',
),
User(
name: "菠萝用户",
email: "pineapple@example.com",
imageAsset: 'assets/images/pineapple.png',
),
];
//UI建造
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
centerTitle: true,//居中标题
),
body: ListView.builder(//构造列表
itemCount: users.length,//列表项总数
//动态构建每个列表项的UI
itemBuilder: (context, index) {//框架自动传递index
final user = users[index];//用index取User对象数据,通过 index实现 ListView与数据的间接关联
return Card(//Card 容器
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),//外边距
child: ListTile(
leading: Image.asset( //左侧图标
user.imageAsset,
width: 50,
height: 50,
errorBuilder: (context, error, stackTrace) {
return const Icon(Icons.error); // 图片加载失败时显示错误图标
},
),
title: Text(user.name),//第一个text
subtitle: Text(user.email),//第二个text
trailing: const Icon(Icons.arrow_forward),//右侧箭头图标
//点击事件
onTap: () {
ScaffoldMessenger.of(context).showSnackBar( //SnackBar底部提示条
SnackBar(
content: Text("选择了: ${user.name}"), //文本提示
action: SnackBarAction(
label: '关闭',
onPressed: () {},
),
),
);
},
),
);
},
),
);
}
}