在这里插入图片描述
在这里插入图片描述

概述

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
代码简洁度
内存占用 低(懒加载) 高(全部创建)
适合场景 大量数据 少量数据
维护难度

关键要点总结

  1. separatorBuilder用于创建分隔符
  2. 分隔符数量为itemCount - 1
  3. 可以自定义分隔符样式,不限于Divider
  4. 适合联系人列表、设置页面等场景
  5. 性能与ListView.builder相当,支持懒加载

常见问题

Q1: 如何在第一个或最后一个列表项添加分隔符?

A: ListView.separated只在列表项之间添加分隔符,不在首尾添加。如需首尾分隔符,需要手动添加。

Q2: 分隔符可以不同吗?

A: 可以,通过index参数判断并返回不同的分隔符。

Q3: 如何实现分组列表?

A: 在itemBuilder中返回分组标题和列表项的组合,separatorBuilder返回分组间距。

Q4: 性能如何?

A: 与ListView.builder相同,支持懒加载,性能优异。

实践建议

  1. 联系人列表:使用Divider作为分隔符
  2. 设置页面:使用Divider或自定义分隔符
  3. 分组列表:在itemBuilder中处理分组逻辑
  4. 大量数据:使用ListView.separated的懒加载特性
  5. 自定义样式:根据设计稿自定义separatorBuilder

通过合理使用ListView.separated,可以创建出清晰、美观的分隔列表,提高用户体验。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐