Flutter: 如何裁剪Column或Row以避免溢出

30
Flutter中我有一个如下的布局结构:
Inkwell
  Card
    ScopedModelDescendant
      Column
        Container[]

列中的容器数量是可变的。

目标是它应该看起来像这样:

expected look

但实际上,它最终效果却是这样的:

actual look

我尝试给Card添加clipBehavior属性,并在结构中混合使用ClipRects,但似乎都不起作用。 我的最佳猜测是在Column之上放置ClipRect没有帮助,因为溢出发生在列内部

这是我得到的错误:

flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════
flutter: The following message was thrown during layout:
flutter: A RenderFlex overflowed by 15 pixels on the bottom.
flutter:
flutter: The overflowing RenderFlex has an orientation of Axis.vertical.
flutter: The edge of the RenderFlex that is overflowing has been marked in the rendering with a yellow and
flutter: black striped pattern. This is usually caused by the contents being too big for the RenderFlex.
flutter: Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the
flutter: RenderFlex to fit within the available space instead of being sized to their natural size.
flutter: This is considered an error condition because it indicates that there is content that cannot be
flutter: seen. If the content is legitimately bigger than the available space, consider clipping it with a
flutter: ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex,
flutter: like a ListView.
flutter: The specific RenderFlex in question is:
flutter:   RenderFlex#094c9 OVERFLOWING
flutter:   creator: Column ← ScopedModelDescendant<EventModel> ← Semantics ← DefaultTextStyle ←
flutter:   AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#5fe8b ink renderer] ←
flutter:   NotificationListener<LayoutChangedNotification> ← CustomPaint ← _ShapeBorderPaint ← PhysicalShape
flutter:   ← _MaterialInterior ← Material ← ⋯
flutter:   parentData: <none> (can use size)
flutter:   constraints: BoxConstraints(w=56.0, h=104.3)
flutter:   size: Size(56.0, 104.3)
flutter:   direction: vertical
flutter:   mainAxisAlignment: start
flutter:   mainAxisSize: max
flutter:   crossAxisAlignment: stretch
flutter:   verticalDirection: down
flutter: ◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤◢◤
flutter: ════════════════════════════════════════════════════════════════════════════════════════════════════
3个回答

69

Wrap小部件可以解决您的问题。如果在ColumnRow中没有足够的空间来适应子级,则可以使用Wrap。您可以使用alignmentdirectionalityspacing属性进行自定义。

这是一个简单的例子:

class WrapExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: 200,
      height: 180,
      child: Card(
        clipBehavior: Clip.antiAlias,
        child: Wrap(
          direction: Axis.horizontal,
          spacing: 8.0, // gap between adjacent chips
          runSpacing: 4.0, // gap between lines
          children: <Widget>[
            Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue.shade900, child: Text('AH')),
              label: Text('Hamilton'),
            ),
            Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue.shade900, child: Text('ML')),
              label: Text('Lafayette'),
            ),
            Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue.shade900, child: Text('HM')),
              label: Text('Mulligan'),
            ),
            Chip(
              avatar: CircleAvatar(
                  backgroundColor: Colors.blue.shade900, child: Text('JL')),
              label: Text('Laurens'),
            ),
          ],
        ),
      ),
    );
  }
}

这是输出结果:

屏幕截图


这个方法很好用!我甚至不需要指定Wrap属性,因为其内部的元素已经有了padding/margin。只需要使用Wrap(children: ...)就行了。在确认完全有效之前,我会再等待一天,但是这个方法解决了我的问题——谢谢! - forresthopkinsa
1
你需要在 Card 组件中设置 clipBehavior 属性。 - Hongli Yu

0

您也可以将想要允许溢出的小部件包装在Stack小部件中的Positioned内,并设置Positioned参数top: 0

对我来说非常有效


-1

这个问题的原因是列部件根据其父级传递的约束确定其尺寸尽可能大。然而,子元素的总大小基于它们所需的内容进行收缩包装,后者更大。

为了解决这个问题,可以采取以下方法:

  • 使列计算基于子元素大小的弹性,而不是默认行为(即根据从父级传递的约束尽可能大)。要做到这一点,请使用FlexibleExpanded小部件包装您的子元素。
  • 使用默认为收缩包装其大小的小部件Wrap,如当前解决方案所建议的。
  • 使用SingleChildScrollView,它会剪切空间,忽略子元素所需的大小。

我不知道为什么有时Column会接受太少空间的约束,以适应其子元素,因为我没有深入研究这个问题。但根据Flutter布局原则,这种情况可能会发生。希望有人能对此提供见解:)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接