例六
Center( child: ConstrainedBox( constraints:const BoxConstraints(maxHeight: 100), child:const SizedBox( width: 300, height:300, child: DecoratedBox( decoration: BoxDecoration(color: Colors.green)))) ); 复制代码
如果父级传过来的是 loose 约束,可以在父级允许的范围内修改.
- Center 传给 BoxConstraints
constraints: BoxConstraints(0.0<=w<=500.0, 0.0<=h<=296.0) 复制代码
- BoxConstraints 传给 SizedBox
constraints: BoxConstraints(0.0<=w<=500.0, 0.0<=h<=100.0)\ 复制代码
- SizedBox 传给 BoxDecoration
BoxConstraints(w=300.0, h=100.0) 复制代码
综合 例五 例六,我们可以得出结论
BoxConstraints,sizedBox 只能在父级允许的范围内做修改。
例七
UnconstrainedBox( child: DecoratedBox(decoration: BoxDecoration(color: Colors.green))); } 复制代码
- app 传给 UnconstrainedBox
constraints: BoxConstraints(w=500.0, h=296.0) 复制代码
- UnconstrainedBox 传给 DecoratedBox
constraints: BoxConstraints(unconstrained) 复制代码
UnconstrainedBox的作用是去掉 contains。BoxDecoration 在没有任何约束的情况下,会显示为最小,也就是 0 x 0 ,所以我们看不见它了。
例八
Directionality( textDirection: TextDirection.ltr, child: Row(children: const [ LimitedBox(maxWidth: 100,maxHeight: 100, child: SizedBox(width: 300,height: 300, child: DecoratedBox(decoration: BoxDecoration(color: Colors.green)), ), ) ])); 复制代码
Directionality 是 row 必须的上级,不然报错。Directionality 不处理 constraints,所以 app直接把 constraints传给了 Row
- app 传给 Row
constraints: BoxConstraints(w=500.0, h=296.0) 复制代码
- Row 修改宽度的 contain 为不限并传给 LimitedBox
constraints: BoxConstraints(0.0<=w<=Infinity, 0.0<=h<=296.0) 复制代码
修改宽度为 Infinity 是 Row 本身的算法。
- LimitedBox 修改 maxWidth 并传给 DecoratedBox
constraints: BoxConstraints(0.0<=w<=100.0, 0.0<=h<=296.0) 复制代码
代码中 LimitedBox 修改了宽高,为什么只有 宽生效呢?
LimitedBox 只能修改 值 为 Infinity 的约束。
- SizedBox 加上自己的约束传给 DecoratedBox
constraints: BoxConstraints(w=100.0, h=296.0) 复制代码
SizedBox 想达到高宽 都为 300 但还得满足在父级允许的范围内。所以 传给 DecoratedBox 的只能是 100 x 296
最终 DecoratedBox 显示为 100 x 296
和 Row 类似,Column会修改高度的 constrain 为 Infinity。
在 Row,Column 中 为了避免错误,一定要注意给children 增加约束。
在前面的例子中, 为了做纯的 constrains 研究,没有用 Container,因为 Container 有自己的特性,如果不知 constrains 的原理,会被它的特性误导,误以为是 constrains 起作用。下面举几个 Container 的例子,说说 Container的特性。
例九
Center( child: Container( color: Colors.green, )); 复制代码
如果直接写Container( color: Colors.green)
会全屏绿好理解,因为是 app 要求 Container必须要显示为全屏,但是现在已经加了Center了啊。为什么还是全屏? 这个就是Container的特性之一,当没有孩子的时候,会尝试尽可能能的大。
例十
Center( child: Container( width: 100, color: Colors.green, ));
例九中有一个词埋下了伏笔。“尝试”尽可能的大。“尝试”结果就是没有孩子,没有约束,尽可能的大,有约束就按约束来。
本例中,高度没有约束,所以占满屏幕,宽度有约束,显示为 100
例十一
Center( child: Container( color: Colors.red[300], child: Container( width: 100, height: 100, color: Colors.green,))); 复制代码
明明外面还有一个红色的 Container,但怎么看不见呢。这时展示了 Container的另一个特性,当它有孩子的时候,尝试尽可能的小。
本例中,因为 Center 让 红色 Container 可以任意大小,只要不超过屏幕,但它有孩子 ,所以它决定要变得和孩子一样大。幸运的是孩子也没有超过屏幕,于是它就和孩子一样大了。但因为孩子的绿色覆盖了它的红色,所以我们看不到它了。
例十一
Center( child: Container( color: Colors.red[300], padding: const EdgeInsets.all(20), child: Container( width: 100, height: 100, color: Colors.green, ))); 复制代码
当有pading的时候,就可以看到 红色的。特别的,这时的红色Container展示为 140 x 140
在没有约束的情况下 padding 越大,Container 越大,但如果是有约束呢?
例十二
Center( child: Container( color: Colors.red[300], padding: const EdgeInsets.all(20), child: Container( padding: const EdgeInsets.all(60), width: 100, height: 100, color: Colors.green, child: Container( width: 50, height: 50, color: Colors.blue[400], ), ))); 复制代码
最里面加了一个 蓝色 Container,但是完全看不到,因为 Container的高宽是包含padding的,绿色Container的高宽为 100,padding 却点了 120,占了所有的空间,所以没有蓝色 Container的显示空间了。padding超出不会报错,超出按最大值算。
作为最后一例,详细解说一下
- app 告诉 Cetner ,你必须 为屏幕大小
- Cetner 告诉 红色 Container 你可以任意大小,但别超过屏幕
- 红色 Container 发自己有 padding ,所以它告诉 绿色 Container ,你可以任意大小,但别超过 (500 - 40) x (296 - 40),因为屏幕的高宽为 500 x 296 ,各减去 padding 40,也就是 460 x 256
- 绿色 Container 同减去 Padding 后告诉 蓝色 Container ,只能显示为 0 x 0
- 蓝色 Container 报告说,好的,我显示 为 0 x 0
- 绿色 Container,报告给 红色 Container 说 ,我显示为 100 x 100
- 红色 Container 报告给 Center 说, 我显示为 460 x 256
- Center 于是 把 红色 Container 放在中间,并上报给 app,我显示为全屏。
如果你完全理解了上面的全部,你就有了布局的坚实的基础了。虽然还有很多布局的 Widget 没有介绍,但原理已经解释了,其它的都可以举一反三。最后还特意介绍了 Container ,以便区分哪些是 约束的效果,哪些是 Container 自己的行为,这样才能更好的理解约束。
如果你觉得有所收获,给我点个贊吧~