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

使用GoRouter ShellRoute出现BoxConstraints无限高度错误的原因与解决

为什么使用go_router的ShellRoute会触发无限高度渲染错误?

当使用go_router的ShellRoute共享BaseWidget时,出现了BoxConstraints forces an infinite height等渲染错误,但直接用BaseWidget包裹组件却完全正常。

问题原因

ShellRoute传入的child本质是一个Navigator组件,它默认会尝试占据父组件的全部可用空间(垂直方向无上限)。而你的BaseWidget使用ListView作为body,ListView的子组件在垂直方向没有固定高度约束(因为ListView自身是可滚动容器),这就导致Navigator无法确定自身的高度,触发了无限高度的布局冲突。

而直接使用BaseWidget的场景中,BodyWidget是一个Column,它的高度由自身子项的总高度决定,ListView可以正确计算它的尺寸,因此不会出现错误。

解决方案

方案一:调整布局结构(推荐)

修改BaseWidget的布局,让child拥有明确的高度约束,同时让内容自身处理滚动:

  1. 更新BaseWidget:
class BaseWidget extends StatelessWidget {
  final Widget child;
  const BaseWidget({super.key, required this.child});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          const FlutterLogo(size: 80),
          // 让child占据剩余屏幕空间
          Expanded(child: child),
        ],
      ),
    );
  }
}
  1. 更新BodyWidget,将Column替换为ListView以支持滚动:
class BodyWidget extends StatelessWidget {
  const BodyWidget({super.key});

  @override
  Widget build(BuildContext context) {
    return ListView(
      children: List.generate(100, (index) {
        return Text(
          "Any text ${index + 1}",
          style: Theme.of(context).textTheme.headlineSmall,
        );
      }),
    );
  }
}

这种方案符合Flutter的布局约束规范,适配性更好,同时保持了组件的可复用性。

方案二:给ShellRoute的child添加明确高度约束

如果不想修改BaseWidget和BodyWidget的结构,可以手动计算可用高度并约束Navigator的尺寸:

ShellRoute(
  builder: (context, state, child) {
    final screenHeight = MediaQuery.of(context).size.height;
    final statusBarHeight = MediaQuery.of(context).padding.top;
    final logoHeight = 80.0;
    // 计算child可用的高度:屏幕高度 - 状态栏高度 - Logo高度
    final availableHeight = screenHeight - statusBarHeight - logoHeight;
    
    return BaseWidget(
      child: SizedBox(
        height: availableHeight,
        child: child,
      ),
    );
  },
  routes: [
    GoRoute(
      path: "/shell",
      builder: (context, state) => const BodyWidget(),
    )
  ]
)

这种方案无需改动原有组件,但需要手动处理高度计算,适配不同设备时需要额外注意。

总结

问题并非go_router的bug,而是布局约束冲突导致的。核心是ShellRoute的Navigator需要明确的高度约束,而原有的ListView布局无法提供这种约束。通过调整布局结构或手动添加约束即可解决问题。

内容的提问来源于stack exchange,提问作者Marcelo Barros

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:00:02