【布局 widget】 Flutter FractionallySizedBox
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 范围。
转载自:https://juejin.cn/post/7168245055285624862