ListView.separated分隔列表 - 鸿蒙Flutter联系人列表场景
·


概述
ListView.separated是ListView的一种特殊构造方式,允许在列表项之间添加自定义分隔符。在联系人列表、设置页面等场景中,分隔符是常见的UI元素,可以提高列表的可读性。
ListView.separated构造函数
ListView.separated({
Key? key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController? controller,
bool? primary,
ScrollPhysics? physics,
EdgeInsetsGeometry? padding,
bool shrinkWrap = false,
double? itemExtent,
Widget? prototypeItem,
required IndexedWidgetBuilder itemBuilder, // 项构建器
required IndexedWidgetBuilder separatorBuilder, // 分隔符构建器
required int itemCount, // 项数量
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
int? semanticChildCount,
})
核心属性详解
separatorBuilder
分隔符构建器,是一个回调函数,接收context和index参数,返回一个Widget作为分隔符:
separatorBuilder: (context, index) {
return Divider(height: 1, color: Colors.grey);
}
itemBuilder
项构建器,与ListView.builder相同:
itemBuilder: (context, index) {
return ListTile(title: Text("Item $index"));
}
itemCount
项数量,分隔符数量为itemCount - 1:
itemCount: 100, // 100个列表项,99个分隔符
基本用法示例
简单分隔列表
ListView.separated(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(title: Text("联系人 $index"));
},
separatorBuilder: (context, index) {
return const Divider(height: 1);
},
)
自定义分隔符
ListView.separated(
itemCount: 20,
itemBuilder: (context, index) {
return ListTile(title: Text("联系人 $index"));
},
separatorBuilder: (context, index) {
return Container(
height: 10,
color: Colors.grey[100],
child: const Center(
child: Text('---'),
),
);
},
)
联系人列表实战
基础联系人列表
ListView.separated(
itemCount: 20,
padding: EdgeInsets.symmetric(vertical: 8),
itemBuilder: (context, index) {
return ListTile(
leading: const CircleAvatar(
child: Icon(Icons.person),
),
title: Text("联系人 $index"),
subtitle: Text("1380000${index.toString().padLeft(4, '0')}"),
trailing: const Icon(Icons.phone),
);
},
separatorBuilder: (context, index) {
return const Divider(height: 1, color: Colors.grey);
},
)
带分组的联系人列表
ListView.separated(
itemCount: 26,
itemBuilder: (context, index) {
final letter = String.fromCharCode(65 + index);
return Column(
children: [
Container(
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
color: Colors.grey[100],
child: Row(
children: [
Text(letter, style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(width: 16),
Text("联系人列表"),
],
),
),
ListTile(
leading: const CircleAvatar(child: Icon(Icons.person)),
title: Text("$letter开头的联系人"),
),
],
);
},
separatorBuilder: (context, index) {
return const SizedBox(height: 8);
},
)
自定义分隔符样式
虚线分隔符
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(title: Text("项目 $index"));
},
separatorBuilder: (context, index) {
return Container(
height: 1,
margin: EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(color: Colors.grey, width: 1, style: BorderStyle.dashed),
),
),
);
},
)
渐变分隔符
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(title: Text("项目 $index"));
},
separatorBuilder: (context, index) {
return Container(
height: 2,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.transparent, Colors.blue, Colors.transparent],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
),
);
},
)
带图标分隔符
ListView.separated(
itemCount: 5,
itemBuilder: (context, index) {
return ListTile(title: Text("菜单项 $index"));
},
separatorBuilder: (context, index) {
return const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Row(
children: [
Expanded(child: Divider()),
Padding(
padding: EdgeInsets.symmetric(horizontal: 8),
child: Icon(Icons.star, size: 12, color: Colors.grey),
),
Expanded(child: Divider()),
],
),
);
},
)
设置页面实战
完整设置页面
ListView.separated(
itemCount: 8,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
final settings = [
{'icon': Icons.person, 'title': '个人信息'},
{'icon': Icons.notifications, 'title': '通知设置'},
{'icon': Icons.lock, 'title': '隐私设置'},
{'icon': Icons.language, 'title': '语言设置'},
{'icon': Icons.display, 'title': '显示设置'},
{'icon': Icons.sound, 'title': '声音设置'},
{'icon': Icons.help, 'title': '帮助与反馈'},
{'icon': Icons.info, 'title': '关于'},
];
return ListTile(
leading: Icon(settings[index]['icon']),
title: Text(settings[index]['title']),
trailing: const Icon(Icons.chevron_right),
);
},
separatorBuilder: (context, index) {
return const Divider(height: 1);
},
)
ListView.separated vs Divider手动添加
// 使用ListView.separated
ListView.separated(
itemCount: 10,
itemBuilder: (context, index) => Text('Item $index'),
separatorBuilder: (context, index) => Divider(),
)
// 使用ListView手动添加Divider
ListView(
children: [
for (int i = 0; i < 10; i++) ...[
Text('Item $i'),
if (i < 9) Divider(),
],
],
)
性能对比
| 特性 | ListView.separated | 手动添加Divider |
|---|---|---|
| 代码简洁度 | 高 | 低 |
| 内存占用 | 低(懒加载) | 高(全部创建) |
| 适合场景 | 大量数据 | 少量数据 |
| 维护难度 | 低 | 高 |
关键要点总结
- separatorBuilder用于创建分隔符
- 分隔符数量为itemCount - 1
- 可以自定义分隔符样式,不限于Divider
- 适合联系人列表、设置页面等场景
- 性能与ListView.builder相当,支持懒加载
常见问题
Q1: 如何在第一个或最后一个列表项添加分隔符?
A: ListView.separated只在列表项之间添加分隔符,不在首尾添加。如需首尾分隔符,需要手动添加。
Q2: 分隔符可以不同吗?
A: 可以,通过index参数判断并返回不同的分隔符。
Q3: 如何实现分组列表?
A: 在itemBuilder中返回分组标题和列表项的组合,separatorBuilder返回分组间距。
Q4: 性能如何?
A: 与ListView.builder相同,支持懒加载,性能优异。
实践建议
- 联系人列表:使用Divider作为分隔符
- 设置页面:使用Divider或自定义分隔符
- 分组列表:在itemBuilder中处理分组逻辑
- 大量数据:使用ListView.separated的懒加载特性
- 自定义样式:根据设计稿自定义separatorBuilder
通过合理使用ListView.separated,可以创建出清晰、美观的分隔列表,提高用户体验。
更多推荐

所有评论(0)