Flutter ListView 组件及各种模式

Flutter ListView 组件及各种模式


一、ListView 是什么?

在 Flutter 中,ListView 是一个用于展示 可滚动列表 的基础组件,它是最常用的滚动组件之一。

你可以把它理解为:

类似于 Android 的 RecyclerView或 iOS 的 UITableView,用于在竖直或水平方向上展示一系列可滚动的条目(items)。


二、ListView 的基本用法

1. 最简单的垂直列表(默认方向)

dart 复制代码
ListView(
  children: [
    ListTile(title: Text('Item 1')),
    ListTile(title: Text('Item 2')),
    ListTile(title: Text('Item 3')),
  ],
)
  • children: 是一个 Widget 列表,代表你要展示的所有子项。
  • 默认是 垂直滚动(从上到下)

三、ListView 的几种构造函数(模式)

Flutter 提供了 多个 ListView 的构造函数,每种适用于不同的使用场景。主要包括:

构造函数 适用场景 特点
ListView 子项数量较少、已知全部子项 直接传入 children列表
ListView.builder 子项数量较多或动态生成(推荐) 按需构建,性能更好,适合长列表
ListView.separated 需要在每个 item 之间添加分隔线或间隔 在 builder 基础上增加分隔 widget
ListView.custom 需要完全自定义滚动行为和 item 布局 使用 SliverChildDelegate,高级用法

我们重点讲解前面 3 种,也是实际开发中最常用的。


四、1. ListView(直接传 children,适合少量固定列表)

用法:

dart 复制代码
ListView(
  children: [
    ListTile(title: Text('首页')),
    ListTile(title: Text('发现')),
    ListTile(title: Text('我的')),
    Container(height: 100, color: Colors.amber, child: Center(child: Text('其他内容'))),
  ],
)

特点:

  • 适合 列表项数量少、固定不变 的情况。
  • 所有的子 Widget 会 一次性构建,如果列表很长(比如 1000 个),会导致性能问题,甚至卡顿。

五、2. ListView.builder(推荐:动态/长列表,按需构建)

用法:

dart 复制代码
ListView.builder(
  itemCount: 20, // 列表项总数
  itemBuilder: (BuildContext context, int index) {
    return ListTile(
      leading: Icon(Icons.star),
      title: Text('Item $index'),
    );
  },
)

参数说明:

参数 说明
itemCount 列表中有多少项
itemBuilder 回调函数,返回每一项的 Widget,参数是 context和当前索引 index

特点:

  • 按需构建(懒加载) ,只构建当前屏幕可见的 item,极大提升性能,是开发长列表的首选。
  • 适合:从网络/数据库加载的数据列表、聊天记录、商品列表等动态内容

六、3. ListView.separated(带分隔线的列表)

用法:

dart 复制代码
ListView.separated(
  itemCount: 10,
  separatorBuilder: (BuildContext context, int index) {
    return Divider(color: Colors.grey); // 分隔线
  },
  itemBuilder: (BuildContext context, int index) {
    return ListTile(
      title: Text('Item $index'),
    );
  },
)

参数说明:

  • separatorBuilder: 用于构建 每一项之间的分隔 Widget ,比如 DividerSizedBox
  • 其它参数同 ListView.builder

效果:

  • 每个 item 之间会显示一个分割线(或其他你定义的间隔组件)。
  • 常用于:列表需要明显区分每一项的场景,如设置页、通讯录等

七、ListView 的滚动方向

默认是 垂直滚动(Axis.vertical) ,但也可以设置为 水平滚动(Axis.horizontal) ,通常配合 ListView.builder使用。

水平滚动的例子(横向列表):

dart 复制代码
ListView.builder(
  scrollDirection: Axis.horizontal, // 水平滚动
  itemCount: 10,
  itemBuilder: (context, index) {
    return Container(
      width: 100,
      margin: EdgeInsets.all(8),
      color: Colors.primaries[index % Colors.primaries.length],
      alignment: Alignment.center,
      child: Text('Item $index'),
    );
  },
)

说明:

  • scrollDirection: Axis.horizontal让列表横向滚动
  • 每个 item 需要指定宽度(比如 width: 100),否则会挤在一起

八、ListView 常用搭配组件

组件 说明 适用场景
ListTile 带图标、标题、副标题的列表项 设置页、菜单列表等
Container 自定义布局容器 列表项内容布局
Card 带阴影的卡片容器 商品列表、内容卡片
Divider / SizedBox 分隔线或间距 分隔列表项
GridView 网格布局(二维列表) 图片墙、瀑布流等
SliverList 高级自定义滚动列表(在 CustomScrollView 中使用) 复杂滚动布局

九、ListView 与其它滚动组件的关系

组件 说明
ListView 基本的垂直/水平列表
SingleChildScrollView + Column 简单滚动容器,但子项全部构建,不适合长列表
CustomScrollView + SliverList 更加灵活的自定义滚动视图,ListView 是其一种实现
GridView 网格形式的滚动列表
PageView 页面横向滑动(比如引导页)

十、ListView 性能优化建议

优化点 建议
列表项很多? 一定要用 ListView.builderseparated,不要用 ListView(children: [])
图片加载慢? 使用 cached_network_image等图片缓存库
cell 复杂? 减少嵌套,优化 widget tree,考虑使用 const构造函数
数据来自网络? 结合 FutureBuilder或状态管理(如 Provider、Riverpod、Bloc)异步加载
滚动卡顿? 检查是否一次性构建太多 widget,尽量使用懒加载模式

十一、总结:ListView 的几种模式对比

模式 构造函数 适用场景 特点
基础列表 ListView(children: []) 列表项少、固定 一次性构建所有子项,简单但性能差
动态列表(推荐) ListView.builder 列表项多、动态生成 按需构建,性能好,适合长列表
带分隔线列表 ListView.separated 需要 item 间分隔 在 builder 基础上增加分隔 widget
自定义滚动 ListView.custom 需要完全控制列表布局 使用 SliverChildDelegate,高级用法
水平列表 ListView(scrollDirection: Axis.horizontal) 横向滑动内容 比如轮播图、横向菜单

十二、完整示例:一个实用的 ListView.builder 列表

dart 复制代码
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('ListView 示例')),
        body: MyListView(),
      ),
    );
  }
}

class MyListView extends StatelessWidget {
  final List<String> items = List.generate(50, (index) => '列表项 ${index + 1}');

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return ListTile(
          leading: Icon(Icons.article),
          title: Text(items[index]),
          onTap: () {
            print('你点击了:${items[index]}');
          },
        );
      },
    );
  }
}
相关推荐
程序员Ctrl喵16 小时前
异步编程:Event Loop 与 Isolate 的深层博弈
开发语言·flutter
前端不太难17 小时前
Flutter 如何设计可长期维护的模块边界?
flutter
小蜜蜂嗡嗡18 小时前
flutter列表中实现置顶动画
flutter
始持19 小时前
第十二讲 风格与主题统一
前端·flutter
始持19 小时前
第十一讲 界面导航与路由管理
flutter·vibecoding
始持19 小时前
第十三讲 异步操作与异步构建
前端·flutter
新镜19 小时前
【Flutter】 视频视频源横向、竖向问题
flutter
黄林晴20 小时前
Compose Multiplatform 1.10 发布:统一 Preview、Navigation 3、Hot Reload 三箭齐发
android·flutter
Swift社区20 小时前
Flutter 应该按功能拆,还是按技术层拆?
flutter
肠胃炎21 小时前
树形选择器组件封装
前端·flutter