话不多说,直接丢报错信息,看看自己是否遇到:

The following assertion was thrown during performLayout():
RenderFlex children have non-zero flex but incoming height constraints are unbounded.
When a column is in a parent that does not provide a finite height constraint, for example if it is
in a vertical scrollable, it will try to shrink-wrap its children along the vertical 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 vertical 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.

讲道理这段阅读理解已经告诉我们问题所在以及如何解决了,不放心可以配合一点源码阅读:在Flutter中可滚动组件的高度是无限(infinte)的,如源码所说:“provides its children with an infinite amount of space.”。这点特性和一些尽可能撑满可用空间的组件如Expanded互斥(Expand在flex布局中用以自动撑满剩下所有空间,其fit属性默认为FlexFit.tight)——因为在可滚动组件中使用Expanded时,Expanded可被分配的空间是无限的,无法渲染,于是抛错。

解决方式也是阅读理解后稍稍发散,不用Expanded这类fit属性为FlexFit.tight的组件就ok了,可以像提示所说的用Flexible代替Expanded(它的fit属性默认为fit属性默认为FlexFit.loose,呈现包裹性,刚好包裹子元素且不会超过最大可用宽(高)度),同时要注意,父Flex类型元素的mainAxisSize一定要设为MainAxisSize.min,否则也会报错,原理也是和上卖弄一样的可用空间无限问题。总结一下,其实垂直可滚动组件中,Column内部不可以也没必要使用任何none-zero的flex元素,所有chidren都用Container即可,如果强迫症也请使用Flexible,而非Expanded。

源码中也给出了正确实践的例子:

/// Widget build(BuildContext context) {
///   return LayoutBuilder(
///     builder: (BuildContext context, BoxConstraints viewportConstraints) {
///       return SingleChildScrollView(
///         child: ConstrainedBox(
///           constraints: BoxConstraints(
///             minHeight: viewportConstraints.maxHeight,
///           ),
///           child: Column(
///             mainAxisSize: MainAxisSize.min,
///             mainAxisAlignment: MainAxisAlignment.spaceAround,
///             children: <Widget>[
///               Container(
///                 // A fixed-height child.
///                 color: const Color(0xff808000), // Yellow
///                 height: 120.0,
///               ),
///               Container(
///                 // Another fixed-height child.
///                 color: const Color(0xff008000), // Green
///                 height: 120.0,
///               ),
///             ],
///           ),
///         ),
///       );
///     },
///   );
/// }

不过源码的实例也是面向特定场景的,实际运用中没必要完全按照例子来,只要做到上面总结的几点就没问题。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐