大家好,我是17。
FractionallySizedBox 是布局 widget,可以给 child tight 约束,多用于按比例填充空白。
BoxConstraints _getInnerConstraints(BoxConstraints constraints) { double minWidth = constraints.minWidth; double maxWidth = constraints.maxWidth; if (_widthFactor != null) { final double width = maxWidth * _widthFactor!; minWidth = width; maxWidth = width; } double minHeight = constraints.minHeight; double maxHeight = constraints.maxHeight; if (_heightFactor != null) { final double height = maxHeight * _heightFactor!; minHeight = height; maxHeight = height; } return BoxConstraints( minWidth: minWidth, maxWidth: maxWidth, minHeight: minHeight, maxHeight: maxHeight, ); } 复制代码
void performLayout() { if (child != null) { child!.layout(_getInnerConstraints(constraints), parentUsesSize: true); size = constraints.constrain(child!.size); alignChild(); } else { size = constraints.constrain(_getInnerConstraints(constraints).constrain(Size.zero)); } } 复制代码
上面两段代码就是 FractionallySizedBox 的布局逻辑。我们从三个方面来描述一下。
- 确定 child 的 constrains
- 确定 自己的大小
- 摆放 child。
确定 child constrains
constrains 是 tight ,FractionallySizedBox 透传 constrains 给 child。
constrains 是 loose,widthFactor 为空,FractionallySizedBox 透传 minWidth,maxWith 给 child;heightFactor 为空,FractionallySizedBox 透传 minHeight,maxHeight 给 child。
constrains 是 loose,widthFactor 不为空, 在 constrains 范围内 给 child 的 width tight 约束;heightFactor 不为空 在 constrains 范围内 给 child 的 height tight 约束。
举个例子:
ConstrainedBox( constraints: const BoxConstraints( minWidth: 0, maxWidth: 100, minHeight: 0, maxHeight: 100), child: FractionallySizedBox( widthFactor: 0.5, child: Container( color: Colors.green[400], ), )); 复制代码
widthFactor 不为空,child 的宽受到 tight 约束,值为 100 * 0.5
等于 50。
heightFactor 为空,FractionallySizedBox 将 约束透传给 child。Container 在没有 child 的情况下会尽量大,所以高度为 100。
widthFactor 和 heightFactor 必须大于 0,可以大于 1 ,所以 child 的大小可以超出 parent
确定自己的大小
简单来说,FractionallySizedBox 的大小不会超过 constrains 的范围。在这个前提下,FractionallySizedBox 尽量和 child 一样大。如果没有 child 尽量取 widthFactor,heightFactor 设定的值。
摆放 child
通过 alignment 参数摆放 child。只有 FractionallySizedBox 与 child 不一样大的时候才会有效果。
应用场景
按比例填充空白
Container( width: 100, height: 100, child: FractionallySizedBox( widthFactor: 0.8, heightFactor: 0.8, decoration: BoxDecoration(border: Border.all(color: Colors.blue,width: 2)), child: Container( color: Colors.green[400], ), )) 复制代码
虽然用 container 的 padding 也能做到空白,但不能弹性变化。
FractionallySizedBox 能用在 Row ,Column 中,但需要用 Flexible 包起来。
FractionallySizedBox 可以允许 child 超出父容器,做溢出效果,但是如果溢出,用 OverflowBox 可读性会更好些。
与 SizedBox 比较
SizedBox 和 FractionallySizedBox 都可以给 child tight 约束。
虽然都可以填充空白,但是场景不同。SizedBox 是在同级的兄弟之间填充空白,FractionallySizedBox 是在父子之间填充空白。
SizedBox 的 child 必须在 constrains 范围之内,FractionallySizedBox 的 child 可以超出 constrains 范围。