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

Flutter布局:如何使Widget高度为同Row内另一Widget的指定比例?

解决思路及代码实现

要让红色Widget的高度以黄色Widget的实际渲染高度为基准(最大为其一半),同时自身文本过长时能自动缩小,你可以用以下两种方式实现:

方法一:GlobalKey动态获取黄色Widget高度(简单直接)

通过GlobalKey获取黄色Widget的渲染高度,动态限制红色Widget的最大高度:

class _MyPageState extends State<MyPage> {
  final yellowKey = GlobalKey();
  double? yellowHeight;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    // 延迟获取高度,确保Widget完成渲染
    WidgetsBinding.instance.addPostFrameCallback((_) {
      if (yellowKey.currentContext != null) {
        final renderBox = yellowKey.currentContext!.findRenderObject() as RenderBox;
        setState(() {
          yellowHeight = renderBox.size.height;
        });
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blue,
      width: double.infinity,
      height: MediaQuery.of(context).size.height * 0.5, // 外层高度由屏幕决定
      child: Row(
        children: [
          // 红色Widget:最大高度为黄色的一半,文本过长自动缩小
          Container(
            color: Colors.red,
            constraints: yellowHeight != null 
                ? BoxConstraints(maxHeight: yellowHeight! / 2) 
                : const BoxConstraints(),
            child: FittedBox(
              child: const Text("红色文本,过长会自动缩小"),
            ),
          ),
          const SizedBox(width: 10),
          // 黄色Widget:用GlobalKey标记以获取高度
          Container(
            key: yellowKey,
            color: Colors.yellow,
            child: FittedBox(
              child: const Text("黄色文本,长度变化会改变自身高度"),
            ),
          ),
        ],
      ),
    );
  }
}

方法二:CustomMultiChildLayout(精准布局控制)

通过自定义多子布局,在布局阶段直接让红色Widget的高度依赖黄色Widget的高度:

class _MyPageState extends State<MyPage> {
  static const yellowId = 1;
  static const redId = 2;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blue,
      width: double.infinity,
      height: MediaQuery.of(context).size.height * 0.5,
      child: CustomMultiChildLayout(
        delegate: _HeightDependentLayoutDelegate(),
        children: [
          LayoutId(
            id: yellowId,
            child: Container(
              color: Colors.yellow,
              child: FittedBox(
                child: const Text("黄色文本,长度变化会改变自身高度"),
              ),
            ),
          ),
          LayoutId(
            id: redId,
            child: Container(
              color: Colors.red,
              child: FittedBox(
                child: const Text("红色文本,过长会自动缩小"),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

class _HeightDependentLayoutDelegate extends MultiChildLayoutDelegate {
  @override
  void performLayout(Size size) {
    // 先布局黄色Widget,获取其实际高度
    final yellowSize = layoutChild(_MyPageState.yellowId, BoxConstraints.loose(size));
    positionChild(_MyPageState.yellowId, Offset(size.width - yellowSize.width, 0));

    // 给红色Widget设置最大高度为黄色的一半,再进行布局
    final redMaxHeight = yellowSize.height / 2;
    final redSize = layoutChild(
      _MyPageState.redId,
      BoxConstraints.loose(Size(size.width - yellowSize.width - 10, redMaxHeight)),
    );
    positionChild(_MyPageState.redId, Offset(0, (yellowSize.height - redSize.height) / 2));
  }

  @override
  bool shouldRelayout(covariant MultiChildLayoutDelegate oldDelegate) {
    return true;
  }
}

说明

  • 两种方案都能满足需求:红色Widget最大高度为黄色Widget的一半,当红色文本过长时,FittedBox会自动缩小文本适配高度,绝不会超过限制。
  • 方法一适合简单场景,代码量少;方法二更适合复杂布局场景,能精准控制子Widget的位置和尺寸。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 03:05:22