You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何在ListView内嵌套多个ListView.builder实现嵌套滚动

问题解答

核心问题答复

  • 同一Widget完全支持使用多个ScrollController,你可以为每一个内部ListView.builder分配独立的ScrollController实例,互不干扰。
  • 你需要的嵌套滚动联动效果可实现,推荐使用滚动通知监听方案,代码改造成本最低。

实现步骤

  1. 声明所有滚动控制器,注意在dispose生命周期销毁避免内存泄漏
// 声明控制器
late ScrollController _mainScrollController;
late ScrollController _innerController1;
late ScrollController _innerController2;
late ScrollController _innerController3;

@override
void initState() {
  super.initState();
  // 初始化控制器
  _mainScrollController = ScrollController();
  _innerController1 = ScrollController();
  _innerController2 = ScrollController();
  _innerController3 = ScrollController();
}

@override
void dispose() {
  // 销毁控制器
  _mainScrollController.dispose();
  _innerController1.dispose();
  _innerController2.dispose();
  _innerController3.dispose();
  super.dispose();
}
  1. 改造嵌套ListView结构,给内部列表套NotificationListener监听越界滚动事件,同时指定内部列表的固定高度
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('AppBar'),
    ),
    body: ListView(
      controller: _mainScrollController,
      children: <Widget>[
        // 第一个内部列表
        SizedBox(
          height: 300, // 必须指定明确高度,按需调整
          child: NotificationListener<OverscrollNotification>(
            onNotification: (notification) {
              // 内部列表滚动越界时,将偏移量转给外层主控制器
              _mainScrollController.position.correctPixels(
                _mainScrollController.offset + notification.overscroll
              );
              _mainScrollController.position.notifyListeners();
              return false;
            },
            child: ListView.builder(
              controller: _innerController1,
              itemCount: 20,
              itemBuilder: (context, index) => ListTile(title: Text('列表1 第$index项')),
            ),
          ),
        ),
        // 第二个内部列表,逻辑同上
        SizedBox(
          height: 300,
          child: NotificationListener<OverscrollNotification>(
            onNotification: (notification) {
              _mainScrollController.position.correctPixels(
                _mainScrollController.offset + notification.overscroll
              );
              _mainScrollController.position.notifyListeners();
              return false;
            },
            child: ListView.builder(
              controller: _innerController2,
              itemCount: 20,
              itemBuilder: (context, index) => ListTile(title: Text('列表2 第$index项')),
            ),
          ),
        ),
        // 第三个内部列表,逻辑同上
        SizedBox(
          height: 300,
          child: NotificationListener<OverscrollNotification>(
            onNotification: (notification) {
              _mainScrollController.position.correctPixels(
                _mainScrollController.offset + notification.overscroll
              );
              _mainScrollController.position.notifyListeners();
              return false;
            },
            child: ListView.builder(
              controller: _innerController3,
              itemCount: 20,
              itemBuilder: (context, index) => ListTile(title: Text('列表3 第$index项')),
            ),
          ),
        ),
      ],
    )
  );
}

注意事项

  • 内部ListView必须指定明确的高度,否则外层滚动容器无法确定子元素尺寸,会触发布局异常。
  • 不要给内部ListView设置shrinkWrap: true,该属性会让内部列表高度适配内容,失去独立滚动能力。
  • 如果内部列表内容不足以撑满自身高度,它本身就无法触发滚动,滑动操作会直接由外层列表接管,属于正常表现。

内容的提问来源于stack exchange,提问作者Kumaresh Chandra Baruri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 03:15:11