Flutter Spacer引发的The ParentDataWidget Expanded(flex: 1) 惨案

问题描述

在flutter控制台中遇到如下报错:

bash 复制代码
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.

The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type StackParentData.

Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a Stack widget.

The ownership chain for the RenderObject that received the incompatible parent data was:
  SizedBox.shrink ← Expanded ← Spacer ← Stack ← ConstrainedBox ← Padding ← Container ← Listener ← _GestureSemantics ← RawGestureDetector ← ⋯

问题分析

网上千篇一律的错误信息,都说是Expanded和Stack的关系问题。

但是排查代码中却没有任何地方使用到Expanded,而且由于报错没有指出在哪个页面,所以,问题一时间僵住了。

最后,通过一个一个注释代码块,确定问题大致代码块,最后按照SizedBox.shrink ← Expanded ← Spacer ← Stack ← ConstrainedBox ← Padding ← Container ← Listener ← _GestureSemantics ← RawGestureDetector ← ⋯顺序

一个一个在页面中排查,排查到Spacer,点击进去查看实现,Spacer的会当场build一个Expanded。

Spacer的源码如下:

dart 复制代码
class Spacer extends StatelessWidget {
  /// Creates a flexible space to insert into a [Flexible] widget.
  ///
  /// The [flex] parameter may not be null or less than one.
  const Spacer({super.key, this.flex = 1})
    : assert(flex > 0);

  /// The flex factor to use in determining how much space to take up.
  ///
  /// The amount of space the [Spacer] can occupy in the main axis is determined
  /// by dividing the free space proportionately, after placing the inflexible
  /// children, according to the flex factors of the flexible children.
  ///
  /// Defaults to one.
  final int flex;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      flex: flex,
      child: const SizedBox.shrink(),
    );
  }
}

可以看到Spacer的build方法中,直接返回了一个Expanded,而Expanded的child是SizedBox.shrink()。这就是问题的根源。

解决方案

找到问题所在的页面,将Expanded和Spacer的关系注释掉,或者将Expanded的child改为Container,或者将Expanded的child改为Container()。

总结

不仅 Expanded 的使用限制在Flex/Row/Column中,Spacer 也有一样的限制。

相关推荐
好的佩奇7 小时前
Dart 之集合元素
android·flutter·dart
深蓝AI10 小时前
Meta 开源用了八年的设计系统 astryx:连坐两天 GitHub 总榜第一,组件库开始写给 agent 的说明书
前端·人工智能
IT_陈寒10 小时前
Vue的watch把我坑惨了,原来要这样用才靠谱
前端·人工智能·后端
1-1=011 小时前
Vue 3 模板语
前端·javascript·vue.js
用户76103044737111 小时前
【转战智能眼镜开发】ROKID AIUI 小游戏 亚马逊标枪项目实战讲解
前端
风卿11 小时前
看着AI写代码太孤独了,来欣赏星云吧:一个DSH 装饰插件
前端·javascript
牧艺11 小时前
弹层不用再手算坐标了:CSS Anchor Positioning 从原理到可上线
前端·javascript·css
用户老李11 小时前
YOLO 目标检测自学教程 07:YOLOv3——多尺度预测
前端
moshuying12 小时前
ESP32 墨水屏金价牌(上):从点亮到把图片推过去
前端
李剑一12 小时前
别再抬杠,前端岗已经没了!无论前后端,我们最终都要成“全干”工程师
前端·面试