Flutter RenderFlex 源码和引发的BUG

12 min read

结论

一个Flex类或子类(如Column)不能成为其他Flex类的子类,其父类需要是Flex类型的(即继承它),否则,它们是无界的(剩余空间无法计算),这导致没有直接的问题,直到另一个孩子试图计算和填补它。

源码

如何布局中包含的flex 因子为null或者为o, 那么该组件wiget 就是一个 unbounded的wiget

/// 1. Layout each child with a null or zero flex factor (e.g., those that are not
///    [Expanded]) with unbounded vertical constraints

Flexible != Flex

Flexible,是指具有flex factor的小组件。

比如 , Column继承自 Flex

///  * [Row], for a horizontal equivalent.
///  * [Flex], if you don't know in advance if you want a horizontal or vertical
///    arrangement.
///  * [Expanded], to indicate children that should take all the remaining room.
///  * [Flexible], to indicate children that should share the remaining room but
///    that may size smaller (leaving some remaining room unused).
///  * [SingleChildScrollView], whose documentation discusses some ways to
///    use a [Column] inside a scrolling container.
///  * [Spacer], a widget that takes up space proportional to its flex value.
///  * The [catalog of layout widgets](https://flutter.dev/widgets/layout/).
class Column extends Flex {...}

而Expanded继承自Flexible, 他是有flex 因子的 int flex = 1,

class Expanded extends Flexible {
  /// Creates a widget that expands a child of a [Row], [Column], or [Flex]
  /// so that the child fills the available space along the flex widget's
  /// main axis.
  const Expanded({
    Key? key,
    int flex = 1,
    required Widget child,
  }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
}

正确的嵌套代码

/// Constraints provided: OK
class RenderFlexPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        children: [
          Text('Column > Text_A'),
          Expanded( // Expanded_A
            child: Column(
              children: [
                Text('Column > Expanded_A > Column > Text_B'),
                Expanded( // Expanded_B
                    child: Text('Column > Expanded_A > Column > Expanded_B'))
              ],
            ),
          )
        ],
      ),
    );
  }
}