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

Flutter布局报错:如何在Row中使用FractionallySizedBox定义子组件尺寸?

问题:FractionallySizedBox作为Row子组件时的布局报错解决

问题场景

尝试将通过FractionallySizedBox指定尺寸的组件作为Row子组件,运行时出现布局报错。

原代码

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Stack(
        children: [
          Positioned(
            top: 50,
            child: Row(
              children: [
                BottomWidget(),
                BottomWidget(),
              ],
            ),
          ),
        ],
      )),
    );
  }
}

class BottomWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Flexible(
      child: FractionallySizedBox(
        widthFactor: 0.25,
        child: Container(
          color: Colors.blue,
        ),
      ),
    );
  }
}

报错信息

════════ Exception caught by rendering library ═════════════════════════════════
The following assertion was thrown during performLayout():
RenderFlex children have non-zero flex but incoming width constraints are unbounded.

When a row is in a parent that does not provide a finite width constraint, for example if it is in a horizontal scrollable, it will try to shrink-wrap its children along the horizontal axis. Setting a flex on a child (e.g. using Expanded) indicates that the child is to expand to fill the remaining space in the horizontal direction.
These two directives are mutually exclusive. If a parent is to shrink-wrap its child, the child cannot simultaneously expand to fit its parent.

Consider setting mainAxisSize to MainAxisSize.min and using FlexFit.loose fits for the flexible children (using Flexible rather than Expanded). This will allow the flexible children to size themselves to less than the infinite remaining space they would otherwise be forced to take, and then will cause the RenderFlex to shrink-wrap the children rather than expanding to fit the maximum constraints provided by the parent.

错误原因

Positioned组件默认未给子级(此处的Row)提供有限宽度约束,Row会尝试收缩包裹子组件;而Flexible让子组件尝试填充剩余空间,同时FractionallySizedBox的widthFactor需要基于确定的父级宽度才能计算尺寸,三者布局逻辑冲突导致报错。

解决方案

核心是给Row提供明确的宽度约束,让FractionallySizedBox有计算尺寸的参考基准,同时移除不必要的Flexible(FractionallySizedBox本身基于父级尺寸缩放,无需Flexible分配空间)。

方案1:给Positioned指定屏幕宽度

修改Positioned,通过MediaQuery获取屏幕宽度,明确Row的可用宽度:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Stack(
        children: [
          Positioned(
            top: 50,
            width: MediaQuery.of(context).size.width,
            child: Row(
              children: [
                BottomWidget(),
                BottomWidget(),
              ],
            ),
          ),
        ],
      )),
    );
  }
}

class BottomWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return FractionallySizedBox(
      widthFactor: 0.25,
      child: Container(
        color: Colors.blue,
        height: 50, // 添加高度以显示组件
      ),
    );
  }
}

方案2:用LayoutBuilder获取父级约束

若不想直接依赖屏幕宽度,可通过LayoutBuilder获取Positioned的可用约束,再传递给子组件:

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Stack(
        children: [
          Positioned(
            top: 50,
            left: 0,
            right: 0, // 让Positioned占满左右可用空间
            child: LayoutBuilder(
              builder: (context, constraints) {
                return Row(
                  children: [
                    BottomWidget(parentWidth: constraints.maxWidth),
                    BottomWidget(parentWidth: constraints.maxWidth),
                  ],
                );
              },
            ),
          ),
        ],
      )),
    );
  }
}

class BottomWidget extends StatelessWidget {
  final double parentWidth;

  const BottomWidget({super.key, required this.parentWidth});

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: parentWidth * 0.25,
      child: Container(
        color: Colors.blue,
        height: 50,
      ),
    );
  }
}

说明

两种方案均解决了宽度约束问题,让FractionallySizedBox(或基于父宽计算的尺寸)正常工作。方案1更直接,方案2适合需要动态获取父级约束的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:22:09