AspectRatio widget 是用来约束宽高比例的,如果你需要 widget 必须要有一定的宽高比,这个组件就很有用。
但 AspectRatio 并不总是如你所愿,我一度想直接设置宽高达到同样的目的,但当你了解了它的逻辑之后,发现这样做并不明智,因为即使是直接设置高度,这些逻辑也是少不了的。
想想也是合理的。如果约束是没有边界的,而 AspectRatio 本身又没有宽高属性,AspectRatio 就无法设置宽高,只能都是无限,就和宽高有比例这个要求相矛盾。
决定宽高的代码
Size _applyAspectRatio(BoxConstraints constraints) {
assert(constraints.debugAssertIsValid());
assert(() {
if (!constraints.hasBoundedWidth && !constraints.hasBoundedHeight) {
throw FlutterError(
'$runtimeType has unbounded constraints.\n'
'This $runtimeType was given an aspect ratio of $aspectRatio but was given '
'both unbounded width and unbounded height constraints. Because both '
"constraints were unbounded, this render object doesn't know how much "
'size to consume.',
);
}
return true;
}());
if (constraints.isTight) {
return constraints.smallest;
}
double width = constraints.maxWidth;
double height;
// We default to picking the height based on the width, but if the width
// would be infinite, that's not sensible so we try to infer the height
// from the width.
if (width.isFinite) {
height = width / _aspectRatio;
} else {
height = constraints.maxHeight;
width = height * _aspectRatio;
}
// Similar to RenderImage, we iteratively attempt to fit within the given
// constraints while maintaining the given aspect ratio. The order of
// applying the constraints is also biased towards inferring the height
// from the width.
if (width > constraints.maxWidth) {
width = constraints.maxWidth;
height = width / _aspectRatio;
}
if (height > constraints.maxHeight) {
height = constraints.maxHeight;
width = height * _aspectRatio;
}
if (width < constraints.minWidth) {
width = constraints.minWidth;
height = width / _aspectRatio;
}
if (height < constraints.minHeight) {
height = constraints.minHeight;
width = height * _aspectRatio;
}
return constraints.constrain(Size(width, height));
}
定好自己的宽高后,把 child 设置成和自己一样宽高
@override
void performLayout() {
size = computeDryLayout(constraints);
if (child != null) {
child!.layout(BoxConstraints.tight(size));
}
}
AspectRatio 的 renderObject 继承自 RenderProxyBox。只可以有一个child,没有 alignment 属性,不能摆放 child的位置。
AspectRatio 的 aspectRatio 参数要求是 大于0 的 double ,但是一般都是用分数的形式来写,这样可读性会更好些。
AspectRatio(
aspectRatio: 1 / 2,
);