如何使小部件的最大尺寸等于一行中的弹性值

How to make a widget maximum size be equal to the flex value in a row

我有这个小代码:

Container(
  color: Colors.blue,
  child: Row(
    children: [
      Expanded(
        child: Container(
          color: Colors.red,
          child: const Text('Red text that can be long long long long long'),
        ),
      ),
      Flexible(
        child: Container(
          color: Colors.green,
          child: const Text('Small text'),
        ),
      ),
    ],
  ),
),

呈现为:

注意长文本是如何换行的,尽管小文本周围仍然有 space。

我希望小文本只占用所需的大小,让长文本占用其余部分。如果小文本变大,它的最大大小将是行中 Flexible 小部件的大小(在我的示例中是 Row 的一半,因为 ExpandedFlexibleflex: 1).

如果小文本足够小,它应该看起来像:

| Red text that can be long long long long | Small text |
| long                                     |            |

如果“小”文本太长:

| Red text that can be long | Small text that is also  |
| long long long long       | very long                |

有办法吗?

绿色可以使用ConstrainedBox:constraints: BoxConstraints.loose( Size.fromWidth(maxWidth / 2)

body:LayoutBuilder( 
  builder: (context, constraints) => Row(
    children: [
      Expanded(
        child: Container(
          color: Colors.red,
          child: const Text(
              'Red text that can be long long long lbe long long long lbe long long long long long'),
        ),
      ),
      ConstrainedBox(
        constraints: BoxConstraints.loose(
            Size.fromWidth(constraints.maxWidth / 2)),
        child: Container(
          color: Colors.green,
          child: const Text('Smalled g long th xt'),
        ),
      ),
    ],
  ),
),
    Row(
    children: <Widget>[
    Expanded(
    child:Container(
      color: Colors.green,
      child: const Text('Small text'),
    ),
   ),
   Expanded(
   child: Container(
      color: Colors.red,
      child: const Text('Small text'),
    ),
   ),
   ]
   )

最后我用了Yeasin Sheikh's 所以我验证一下

但我写这篇评论是为了更加精确地说明我在调查中发现的内容。


起初,我想要一个像 FlexibleExpanded(比方说 LooseFlexible)这样的简单小部件来包装我的小部件:

View upvote and downvote totals.

I have this small code:

Container(
  color: Colors.blue,
  child: Row(
    children: [
      Expanded(
        child: Container(
          color: Colors.red,
          child: const Text('Red text that can be long long long long long'),
        ),
      ),
      LooseFlexible(
        flex: 1
        child: Container(
          color: Colors.green,
          child: const Text('Small text'),
        ),
      ),
    ],
  ),
),

但这似乎违背了 Flutter 的工作方式。

我看了一下flutterclassRenderFlex,这是renderobjectFlexclass(一个class RowColumn 正在扩展)returns 在方法 createRenderObject 中。 它有一个方法_computeSizes,在里面它通过children(一个接一个):

  • 如果它没有 flex 值(“普通小部件”): 它为 child 提供了布局的无最大约束并获取其大小。
  • 如果它有一个 flex 值(来自 FlexibleExpanded): 它在 totalFlex 值中累积了所有 flex 中的一些值(并且 呈现 child)。

然后它遍历所有具有 flex 值的小部件,并将它们作为最大约束 (flex / totalFlex) * (maxConstraintOfParent - totalSizeOfNonFlexChildren) 并使用它进行布局。

所以每个child布局只有一次


如果我的小部件 LooseFlexible 存在,并且我们有此代码:

Row(
  children: [
    Expanded(flex: 1),
    LooseFlexible(flex: 1),
    Expanded(flex: 1),
  ],
),

假设该行的 maxWidth300。没有non-flexchildren和totalFlex = 3.

  1. 第一个 Expanded 将使用 maxWidth = 100 进行布局。因为它是一个 Expanded,它的 width 将是 100.
  2. Flexible 小部件也使用 maxWidth = 100 布局。但它的大小可能是 50(而不是 100)。
  3. 现在轮到最后一个 Expanded,如果我们想让它占据整个剩余的 space,它的大小将是 150,这与第一个不一样Expanded 具有相同的 flex = 1 值。所以第一个 child 需要被 re-laid 出来,这不遵循 flutter 渲染方式 children only once.