最近在看Flutter组件详解与实战书籍
flutter组件内部有个constraints约束的概念
首先一切皆组件包括 样式 布局 滚动 动画 约束 人机交互 触摸拖放
有了基础组件会层层封装成新的语法糖组件比如 flex 构成 Column Row 有多个组件构成的Continer
container根据不同的参数包装不同的组件有外而内如下:
- ConstrainedBox
- LimitedBox
- Align
- Padding
- ColoredBox
- ClipPath
- DecoratedBox
- ConstrainedBox
- Padding
- Transform 可以参考web盒模型 里面属性有冲突自行选择比如color与decoration 这里width height 可以构成BoxConstraints
- child与BoxConstraints 空情况 渲染内部LimitedBox->ConstrainedBox
- 渲染外部ConstrainedBox
Container({
super.key,
this.alignment,
this.padding,
this.color,
this.decoration,
this.foregroundDecoration,
double? width,
double? height,
BoxConstraints? constraints,
this.margin,
this.transform,
this.transformAlignment,
this.child,
this.clipBehavior = Clip.none,
}) : assert(margin == null || margin.isNonNegative),
assert(padding == null || padding.isNonNegative),
assert(decoration == null || decoration.debugAssertIsValid()),
assert(constraints == null || constraints.debugAssertIsValid()),
assert(decoration != null || clipBehavior == Clip.none),
assert(
color == null || decoration == null,
'Cannot provide both a color and a decoration\n'
'To provide both, use "decoration: BoxDecoration(color: color)".',
),
constraints =
(width != null || height != null)
? constraints?.tighten(width: width, height: height) ??
BoxConstraints.tightFor(width: width, height: height)
: constraints;
@override
Widget build(BuildContext context) {
Widget? current = child;
if (child == null && (constraints == null || !constraints!.isTight)) {
current = LimitedBox(
maxWidth: 0.0,
maxHeight: 0.0,
child: ConstrainedBox(constraints: const BoxConstraints.expand()),
);
} else if (alignment != null) {
current = Align(alignment: alignment!, child: current);
}
final EdgeInsetsGeometry? effectivePadding = _paddingIncludingDecoration;
if (effectivePadding != null) {
current = Padding(padding: effectivePadding, child: current);
}
if (color != null) {
current = ColoredBox(color: color!, child: current);
}
if (clipBehavior != Clip.none) {
assert(decoration != null);
current = ClipPath(
clipper: _DecorationClipper(
textDirection: Directionality.maybeOf(context),
decoration: decoration!,
),
clipBehavior: clipBehavior,
child: current,
);
}
if (decoration != null) {
current = DecoratedBox(decoration: decoration!, child: current);
}
if (foregroundDecoration != null) {
current = DecoratedBox(
decoration: foregroundDecoration!,
position: DecorationPosition.foreground,
child: current,
);
}
if (constraints != null) {
current = ConstrainedBox(constraints: constraints!, child: current);
}
if (margin != null) {
current = Padding(padding: margin!, child: current);
}
if (transform != null) {
current = Transform(transform: transform!, alignment: transformAlignment, child: current);
}
return current!;
}
现在来个demo分析书中提到情况 结构 column->container->container 在 Column 中,x 轴(横向、cross axis)对孩子通常是有界约束(bounded),不是无界。
- 默认行为:Column 会把自身可用的最大宽度作为子组件的 maxWidth。
- crossAxisAlignment.stretch:对子组件给紧约束(minWidth = maxWidth = 可用宽度,铺满)。
- 其它对齐方式:给松约束(0..maxWidth),子组件可变窄但不能超过可用宽度。
- 例外:只有当父级在横向本身就是无界(如某些横向滚动/未限宽场景)时,Column 的 x 轴才可能变成无界,这并非常见。
- 易混点:无界更常发生在 Column 的主轴 y 轴(比如放进纵向 SingleChildScrollView),与 x 轴无关。 LimitedBox 的作用是:当父组件在某个方向上给的是“无界约束”(unbounded)时,只在该方向为子组件施加一个“最大尺寸”限制;若父组件已给出有界约束,则 LimitedBox 不起作用(直接透传)。
要点
- 只在无界方向生效:如滚动方向里的子项(ListView/SingleChildScrollView 中的 children)、Row/Column 某些场景。
- 常用来防止子组件在无界约束下无限扩张,给出上限。
- 构造参数 maxWidth/maxHeight(默认是无穷大),一般需要显式设置为期望的上限。
- 与其他约束组件对比:
- ConstrainedBox:无论父约束是否无界,都应用限制。
- SizedBox:给出紧约束(固定尺寸/最小=最大)。
- LimitedBox:仅在父约束无界时应用最大限制,其他情况不干预。
- 无子组件
1.1 y轴 无界约束 高度为0 x轴 有界约束 宽度为0 撑满Column( children: [ Container( // width: 200, // height: 200, foregroundDecoration: BoxDecoration( color: Colors.grey.withOpacity(0.5), shape: BoxShape.circle, ), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.black,Colors.grey] ), boxShadow: [BoxShadow(blurRadius: 10)] ), alignment: Alignment.center, // child: Container( // color: Colors.orange, // width: 50, // height: 50, // ), ) ], ),
1.2 y轴 有界约束 高度为200 x轴 有界约束 宽度为200
Column(
children: [
Container(
width: 200,
height: 200,
foregroundDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
shape: BoxShape.circle,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black,Colors.grey]
),
boxShadow: [BoxShadow(blurRadius: 10)]
),
alignment: Alignment.center,
// child: Container(
// color: Colors.orange,
// width: 50,
// height: 50,
// ),
)
],
),
2. 有子元素
2.1 无alignment属性
2.1.1 y轴 有界约束 高度为200 x轴 有界约束 宽度为200
Column(
children: [
Container(
width: 200,
height: 200,
foregroundDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
shape: BoxShape.circle,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black,Colors.grey]
),
boxShadow: [BoxShadow(blurRadius: 10)]
),
// alignment: Alignment.center,
child: Container(
color: Colors.orange,
width: 50,
height: 50,
),
)
],
),
2.1.2 y轴 无界约束 高度为0 x轴 无界约束 宽度为0
Column(
children: [
Container(
// width: 200,
// height: 200,
foregroundDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
shape: BoxShape.circle,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black,Colors.grey]
),
boxShadow: [BoxShadow(blurRadius: 10)]
),
// alignment: Alignment.center,
child: Container(
color: Colors.orange,
width: 50,
height: 50,
),
)
],
),
2.2 无alignment属性
2.2.1 y轴 有界约束 高度为200 x轴 有界约束 宽度为200
Column(
children: [
Container(
width: 200,
height: 200,
foregroundDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
shape: BoxShape.circle,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black,Colors.grey]
),
boxShadow: [BoxShadow(blurRadius: 10)]
),
alignment: Alignment.center,
child: Container(
color: Colors.orange,
width: 50,
height: 50,
),
)
],
)
2.2.2 y轴 无界约束 高度为0 x轴 无界约束 宽度为0
Column(
children: [
Container(
// width: 200,
// height: 200,
foregroundDecoration: BoxDecoration(
color: Colors.grey.withOpacity(0.5),
shape: BoxShape.circle,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.black,Colors.grey]
),
boxShadow: [BoxShadow(blurRadius: 10)]
),
alignment: Alignment.center,
child: Container(
color: Colors.orange,
width: 50,
height: 50,
),
)
],
),
1.规律 判断有没有child 没有child 父有界约束走 BoxConstraints.expand() 有child 没有alignment 自身有界约束 子有界约束 有child 有alignment 自身有界约束 父有界约束