首页 > 解决方案 > 如何检测小部件中的溢出

问题描述

我想知道是否有办法检测小部件中发生的溢出并返回一个布尔值以根据truefalse值进行一些更改。

例如,我有一个里面有文本的容器。我想检测文本何时溢出容器,之后我会在某些条件下使容器变大。我知道有一些方法,auto_size_text但这里的重点是检测溢出

标签: flutterflutter-layoutflutter-widget

解决方案


试图检测何时发生溢出,对我来说似乎是一个XY 问题

在 Flutter 中,子部件的大小受其父部件的限制,很少有可能发生溢出的情况。例如,考虑下面的代码:

Container(
  height: 100,
  width: 100,
  color: Colors.red,
  child: Container(
    width: 200,
    height: 800,
    color: Colors.green,
  ),
)

对于没有经验的 Flutter 开发者来说,看起来内部 Container (200x800) 会溢出其父级 (100x100),但实际上,内部的大小会自动调整以匹配其父级,因此您不会看到黑色/黄色溢出条纹,您只会在屏幕上看到一个 100x100 的绿色容器。

那么,我们什么时候可以期待孩子们在 Flutter 中溢出呢?通常有 4 种情况会溢出:

  1. Flex:常用的ColumnwidgetsRow继承自Flexwidget,也可以直接使用。在这些小部件中,当执行布局时,它们将在其主轴上传递一个“无界”约束。例如,在 a 的情况下Column,它的主轴是垂直轴,所以它允许它的孩子们想多高(但不要多宽)。如果它的子元素的组合高度超过了它自身的布局约束Column(由 Column 的父元素传递),它将溢出。基本上,如果您将 Column 放在 100x100 Container 内,则 Column 的高度不能超过 100,如果它的子级超过,它就会溢出。

对于这些情况,检测是可行的,但通常是不必要的。例如,要检测,您可以首先使用LayoutBuilder获取Column自身的父母约束,这样您就知道您可能拥有的最大尺寸是多少(比如 100x100,因为 Column 放置在这样的 Container 中),然后您需要获取每个孩子的大小,这对于 Column 来说不太容易,因为在布局过程完成之前您不会知道它们的大小。(如果您必须在布局完成之前知道它们的大小,您可以考虑查看CustomMultiChildLayout或编写自定义RenderBox)。您也许可以使用GlobalKey来获取任何小部件的大小,但必须在下一帧中完成,一旦孩子们第一次布局。

或许这里要问一个更好的问题:你为什么想知道它是否会溢出?如果它溢出,你能做什么?如果您可以为 Column 分配更多空间,那么为什么不首先这样做呢?您可以设置MainAxisSize.minColumn 来告诉它缩小,除非它真的需要,否则不要浪费所有这些额外的空间。或者,也许您想允许滚​​动?Column如果是这样,只需用一个小部件包裹整个SingleChildScrollView,它就会在 Column 长得太高时自动开始滚动。(顺便说一句,这与 using 不同,如果您有很多要滚动的项目,则ListView应该使用。)ListView

  1. 堆栈:堆栈中的小部件,尤其是那些小部件,Positioned如果您故意这样做,可能会溢出堆栈。例如,通过设置,left: -10, top: -20您会有意地在边界之外渲染一个小部件(略高于左上角)。但是堆栈会自动为您剪辑它,因此您甚至不会看到那些溢出的内容。要查看它们,您实际上需要手动更改clipBehavior堆栈。如果您正在做所有这些工作,我认为“检测算法”并不是完全必要的。

  2. 文本:文本很棘手,取决于字体大小(甚至可能由用户在系统级别修改)、字体粗细、字体系列和许多其他因素,很难计算一个段落将占用多少空间。这是TextPainter可以用来帮助您进行所有计算的地方,layout首先是文本,然后您可以阅读它的宽度和高度。

  3. OverflowBox:Flutter 中其他可能的溢出方式是故意使用OverflowBoxorSizedOverflowBox等​​小部件。这些小部件故意打破父约束,但如果你使用这些,我相信你知道你在做什么。根据用例,您可以考虑使用CustomMultiChildLayout获取每个孩子的大小,然后再决定将它们放置在哪里。

最后的评论:由于您可能想要一个“通用解决方案”,所以这里是:在 Flutter 中,大多数事情都不会溢出。如果需要,LayoutBuilder小部件可用于确定小部件的当前布局约束,因此您知道父母希望您成为的最大和最小尺寸。要获取子小部件的大小,最好的方法是在布局过程中使用CustomSingleChildLayoutCustomMultiChildLayout在布局过程中使用。要获取屏幕上已存在的任何小部件的大小和位置,您可以使用GlobalKey. 但是,通常更重要的是考虑为什么要知道这些尺寸,而不是如何获得它们。


推荐阅读