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

嵌套在PageView及SingleChildScrollView中的ListView.builder出现无限高度错误

问题:实现全屏滚动而非仅ListView滚动

Flutter环境信息

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.3.9, on Microsoft Windows [Version 10.0.19044.2251], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
[√] Chrome - develop for the web
[X] Visual Studio - develop for Windows
    X Visual Studio not installed; this is necessary for Windows development.
      请前往微软官网下载Visual Studio,并安装包含所有默认组件的“使用C++的桌面开发”工作负载
[√] Android Studio (version 2021.3)
[√] VS Code (version 1.74.0)
[√] Connected device (4 available)
[√] HTTP Host Availability

! Doctor found issues in 1 category.

最小复现代码

import 'package:flutter/material.dart';

class Temp extends StatefulWidget {
  const Temp({Key? key}) : super(key: key);

  @override
  State<Temp> createState() => _TempState();
}

class _TempState extends State<Temp> {
  @override
  Widget build(BuildContext context) {
    PageController pageController = PageController(
      initialPage: 0,
    );

    return Scaffold(
      body: Container(
        padding: const EdgeInsets.symmetric(horizontal: 30),
        margin:
            EdgeInsets.only(top: MediaQuery.of(context).viewPadding.top + 10),
        child: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              Container(
                  color: Colors.orangeAccent,
                  height: MediaQuery.of(context).size.height * 0.3,
                  width: MediaQuery.of(context).size.width,
                  child: const Center(child: Text('DUMMY BOX 3'))),
              Container(
                  color: Colors.purpleAccent,
                  height: MediaQuery.of(context).size.height * 0.2,
                  width: MediaQuery.of(context).size.width,
                  child: const Center(child: Text('DUMMY BOX 2'))),
              Container(
                color: Colors.lightBlueAccent,
                height: MediaQuery.of(context).size.height * 0.3,
                width: MediaQuery.of(context).size.width,
                child: const Center(
                  child: Text('DUMMY BOX 3'),
                ),
              ),
              const SizedBox(
                height: 40,
              ),
              PageView(
                controller: pageController,
                children: const [
                  DummyListViewContainerWidget(),
                  DummyListViewContainerWidget(),
                  DummyListViewContainerWidget()
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class DummyListViewContainerWidget extends StatelessWidget {
  const DummyListViewContainerWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
        // physics: const NeverScrollableScrollPhysics(),
        shrinkWrap: true,
        itemCount: 10,
        padding: const EdgeInsets.only(bottom: 20),
        separatorBuilder: (cxt, index) {
          return const SizedBox(
            height: 10,
          );
        },
        itemBuilder: (cxt, index) {
          return Container(
            height: 50,
            width: MediaQuery.of(context).size.width,
            color: Colors.brown,
            child: Center(child: Text(index.toString())),
          );
        });
  }
}

期望效果

整个屏幕可滚动,而非仅ListView可滚动。

已尝试方案

  • 给SingleChildScrollView下方的Column设置MainAxisSize.min
  • 给PageView设置固定高度,但此方案会截断ListView内容,不符合需求
  • 移除顶部的SingleChildScrollView,将其放入PageView内部

解决方案

要实现全屏滚动,需让外部SingleChildScrollView接管整个页面滚动,同时禁止内部ListView的滚动,并让PageView自适应子内容高度,具体修改如下:

  1. 禁止内部ListView滚动:在DummyListViewContainerWidget的ListView.separated中添加physics: const NeverScrollableScrollPhysics(),让内部ListView不再拦截滚动事件,将滚动操作交给外部的SingleChildScrollView。

  2. 让PageView自适应高度:用IntrinsicHeight包裹PageView,该组件会让PageView的高度适配其最高子项的高度,确保PageView能完全展示内部ListView的所有内容,同时让外部SingleChildScrollView可以滚动整个页面。

修改后的DummyListViewContainerWidget

class DummyListViewContainerWidget extends StatelessWidget {
  const DummyListViewContainerWidget({
    Key? key,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return ListView.separated(
        physics: const NeverScrollableScrollPhysics(), // 禁止内部滚动
        shrinkWrap: true,
        itemCount: 10,
        padding: const EdgeInsets.only(bottom: 20),
        separatorBuilder: (cxt, index) {
          return const SizedBox(
            height: 10,
          );
        },
        itemBuilder: (cxt, index) {
          return Container(
            height: 50,
            width: MediaQuery.of(context).size.width,
            color: Colors.brown,
            child: Center(child: Text(index.toString())),
          );
        });
  }
}

修改后的PageView部分

IntrinsicHeight(
  child: PageView(
    controller: pageController,
    children: const [
      DummyListViewContainerWidget(),
      DummyListViewContainerWidget(),
      DummyListViewContainerWidget()
    ],
  ),
),

修改完成后,整个页面(包括上方三个盒子和下方PageView内的所有列表项)均可通过外部的SingleChildScrollView滚动,同时PageView仍支持横向切换页面。


内容的提问来源于stack exchange,提问作者Anas Yousuf

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 20:55:21