新建项目-4.png

Flex 有一个必填参数:direction,用于确定主轴的方向,然后就可以在 children 里写 子Widget

  1. class Flex extends MultiChildRenderObjectWidget {
  2. Flex({
  3. Key key,
  4. @required this.direction,
  5. this.mainAxisAlignment = MainAxisAlignment.start,
  6. this.mainAxisSize = MainAxisSize.max,
  7. this.crossAxisAlignment = CrossAxisAlignment.center,
  8. this.textDirection,
  9. this.verticalDirection = VerticalDirection.down,
  10. this.textBaseline,
  11. List<Widget> children = const <Widget>[],
  12. }) : assert(direction != null),
  13. assert(mainAxisAlignment != null),
  14. assert(mainAxisSize != null),
  15. assert(crossAxisAlignment != null),
  16. assert(verticalDirection != null),
  17. assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null),
  18. super(key: key, children: children);
  19. ...
  20. }

因为Row继承于Flex所有大部分属性Flex都是一样的.具体看Row的总结
Flutter Row

Flexible 与 Expanded

以下内容来自:
Flutter 布局 Widget —— 弹性布局

如果当 Flex 里的内容过长,超过主轴的大小,例如如下的代码:

  1. Flex(
  2. direction: Axis.horizontal,
  3. mainAxisAlignment: MainAxisAlignment.start,
  4. children: <Widget>[
  5. Text('Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!')
  6. ],
  7. )

image.png

为了避免 子Widget 在 Row、Column、Flex 中超界,就可以使用 Flexible 与 Expanded。Flexible 与 Expanded 可以让 Row、Column、Flex 的 子Widget 具有弹性能力。

比如上面的例子用 Flexible 或 Expended 来改写:

  1. Flexible(
  2. child: Text(
  3. 'Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!'
  4. ),
  5. )

image.png

  1. Expanded(
  2. child: Text(
  3. 'Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!Flutter!'
  4. ),
  5. ),

image.png

用 Flexible 与 Expanded 来包 子Widget,当 子Widget 要超过主轴的大小时,会自动换行,但是 Flexible 与 Expanded 也有不同的地方,Expanded 是 Flexible 的子类。

Flexible 与 Expanded 区别

Flexible构造函数:

  1. const Flexible({
  2. Key key,
  3. this.flex = 1, //此 Widget 的弹性因子
  4. this.fit = FlexFit.loose, //如何分配 弹性Widget 在可用空间里的大小
  5. @required Widget child,
  6. }) : super(key: key, child: child);

Expanded 构造函数:

  1. const Expanded({
  2. Key key,
  3. int flex = 1, //此 Widget 的弹性因子
  4. @required Widget child,
  5. }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);

可以明显看到,Flexible 和 Expanded 的 fit 参数不同,Flexible 的 fit 是 FlexFit.loose,Expanded 的 fit 参数是 FlexFit.tight。所以,当还有剩余空间时,Expanded 会占满剩余的所有空间,而 Flexible 只会占用自身大小的空间。

  1. Flexible(
  2. child: Container(
  3. color: Colors.yellow,
  4. child: Text('使用 Flexible 来包裹 子Widget'),
  5. ),
  6. ),
  1. Expanded(
  2. child: Container(
  3. color: Colors.yellow,
  4. child: Text('使用 Expanded 来包裹 子Widget'),
  5. ),
  6. ),

image.png

Flexible 会占用自身大小,而 Expanded 会占满全屏幕。

总结

Flexible 与 Expanded 可以让 Row、Column、Flex 的 子Widget 具有弹性能力,当 子Widget 要超过主轴的大小时,会自动换行,当还有剩余空间时,Expanded 会占满剩余的所有空间,而 Flexible 只会占用自身大小的空间。

Fexible 和 Expanded 的 flex 弹性系数

Fexible 和 Expanded 还有一个很重要的参数:flex,flex 为弹性系数,其布局过程如下:

  1. 如果 flex 为0或null,则 child 是没有弹性的,称为 非弹性子Widget,非弹性子Widget 的大小就是其本身的大小,不会被扩展去占用多余的空间。
  2. 如果 flex 大于0,child 是有弹性的,称为 弹性子Widget,首先会计算出第一步所有 flex为0或null 的 子Widget 的大小,然后会会按照 弹性子Widget的flex 占 所有弹性子Widget的flex 总和 的比例来分割主轴的空闲空间。
  1. child: Flex(
  2. direction: Axis.horizontal,
  3. mainAxisAlignment: MainAxisAlignment.start,
  4. children: <Widget>[
  5. Flexible(
  6. flex: 1,
  7. child: Container(
  8. height: 30,
  9. width: 30,
  10. color: Colors.yellow,
  11. ),
  12. ),
  13. Flexible(
  14. flex: 2,
  15. child: Container(
  16. height: 30,
  17. width: 30,
  18. color: Colors.red,
  19. ),
  20. ),
  21. Flexible(
  22. flex: 1,
  23. child: Container(
  24. height: 30,
  25. width: 30,
  26. color: Colors.orange,
  27. ),
  28. ),
  29. ],
  30. ),

三个 Flexible 的 flex : 1、2、1
image.png

因为 子Widget 的宽度是固定的,所以 Flexible 只会占用本身的大小。

  1. child: Flex(
  2. direction: Axis.horizontal,
  3. mainAxisAlignment: MainAxisAlignment.start,
  4. children: <Widget>[
  5. Expanded(
  6. flex: 1,
  7. child: Container(
  8. height: 30,
  9. width: 30,
  10. color: Colors.yellow,
  11. ),
  12. ),
  13. Expanded(
  14. flex: 2,
  15. child: Container(
  16. height: 30,
  17. width: 30,
  18. color: Colors.red,
  19. ),
  20. ),
  21. Expanded(
  22. flex: 1,
  23. child: Container(
  24. height: 30,
  25. width: 30,
  26. color: Colors.orange,
  27. ),
  28. ),
  29. ],
  30. ),

Expanded 包裹三个宽高都为 30 的色块,并设置 flex 为 1、2、1

image.png

虽然三个色块的宽度是固定的,但是 Expanded 还是按照比例瓜分了剩余的全部空间。