First child: “OK,那我想要 290
像素的宽度,20
个像素的高度。”
Widget: “嗯…由于我想要将我的第二个子级放在第一个子级下面,所以我们仅剩 55
个像素的高度给第二个子级了。”
Widget: “嘿,我的第二个子级,你的宽度必须要在 0
到 290
,高度在 0
到 55
之间。”
Second child: “OK,那我想要 140
像素的宽度,30
个像素的高度。”
Widget: “很好。我的第一个子级将被放在 x: 5
& y: 5
的位置, 而我的第二个子级将在 x: 80
& y: 25
的位置。”
Widget: “嘿,我的父级,我决定我的大小为 300
像素宽度,60
像素高度。”
限制
正如上述所介绍的布局规则中所说的那样, Flutter 的布局引擎有一些重要限制:
-
一个 widget 仅在其父级给其约束的情况下才能决定自身的大小。 这意味着 widget 通常情况下 不能任意获得其想要的大小。
-
一个 widget 无法知道,也不需要决定其在屏幕中的位置。 因为它的位置是由其父级决定的。
-
当轮到父级决定其大小和位置的时候,同样的也取决于它自身的父级。 所以,在不考虑整棵树的情况下,几乎不可能精确定义任何 widget 的大小和位置。
样例
下面的示例由 DartPad 提供,具有良好的交互体验。 使用下面水平滚动条的编号切换 29 个不同的示例。
你可以在 flutter.cn 上找到该源码。
如果你愿意的话,你还可以在 这个 Github 仓库中 获取其代码。
以下各节将介绍这些示例。
样例 1
Container(color: Colors.red)
整个屏幕作为 Container
的父级,并且强制 Container
变成和屏幕一样的大小。
所以这个 Container
充满了整个屏幕,并绘制成红色。
样例 2
Container(width: 100, height: 100, color: Colors.red)
红色的 Container
想要变成 100 x 100 的大小, 但是它无法变成,因为屏幕强制它变成和屏幕一样的大小。
所以 Container
充满了整个屏幕。
样例 3
Center(
child: Container(width: 100, height: 100, color: Colors.red)
)
屏幕强制 Center
变得和屏幕一样大,所以 Center
充满了屏幕。
然后 Center
告诉 Container
可以变成任意大小,但是不能超出屏幕。 现在,Container
可以真正变成 100 × 100 大小了。
样例 4
Align(
alignment: Alignment.bottomRight,
child: Container(width: 100, height: 100, color: Colors.red),
)
与上一个样例不同的是,我们使用了 Align
而不是 Center
。
Align
同样也告诉 Container
,你可以变成任意大小。 但是,如果还留有空白空间的话,它不会居中 Container
。 相反,它将会在允许的空间内,把 Container
放在右下角(bottomRight)。
样例 5
Center(
child: Container(
color: Colors.red,
width: double.infinity,
height: double.infinity,
)
)
屏幕强制 Center
变得和屏幕一样大,所以 Center
充满屏幕。
然后 Center
告诉 Container
可以变成任意大小,但是不能超出屏幕。 现在,Container
想要无限的大小,但是由于它不能比屏幕更大, 所以就仅充满屏幕。
样例 6
Center(child: Container(color: Colors.red))
屏幕强制 Center
变得和屏幕一样大,所以 Center
充满屏幕。
然后 Center
告诉 Container
可以变成任意大小,但是不能超出屏幕。 由于 Container
没有子级而且没有固定大小,所以它决定能有多大就有多大, 所以它充满了整个屏幕。
但是,为什么 Container
做出了这个决定? 非常简单,因为这个决定是由 Container
widget 的创建者决定的。 可能会因创造者而异,而且你还得阅读 Container
文档 来理解不同场景下它的行为。
样例 7
Center(
child: Container(
color: Colors.red,
child: Container(color: Colors.green, width: 30, height: 30),
)
)
屏幕强制 Center
变得和屏幕一样大,所以 Center
充满屏幕。
然后 Center
告诉红色的 Container
可以变成任意大小,但是不能超出屏幕。 由于 Container
没有固定大小但是有子级,所以它决定变成它 child 的大小。
然后红色的 Container
告诉它的 child 可以变成任意大小,但是不能超出屏幕。
而它的 child 是一个想要 30 × 30 大小绿色的 Container
。由于红色的 Container
和其子级一样大,所以也变为 30 × 30。由于绿色的 Container
完全覆盖了红色 Container
, 所以你看不见它了。
样例 8
Center(
child: Container(
color: Colors.red,
padding: const EdgeInsets.all(20.0),
child: Container(color: Colors.green, width: 30, height: 30),
)
)
红色 Container
变为其子级的大小,但是它将其 padding 带入了约束的计算中。 所以它有一个 30 x 30 的外边距。由于这个外边距,所以现在你能看见红色了。 而绿色的 Container
则还是和之前一样。
样例 9
ConstrainedBox(
constraints: BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: Colors.red, width: 10, height: 10),
)
你可能会猜想 Container
的尺寸会在 70 到 150 像素之间,但并不是这样。 ConstrainedBox
仅对其从其父级接收到的约束下施加其他约束。
在这里,屏幕迫使 ConstrainedBox
与屏幕大小完全相同, 因此它告诉其子 Widget
也以屏幕大小作为约束, 从而忽略了其 constraints
参数带来的影响。
样例 10
Center(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: Colors.red, width: 10, height: 10),
)
)
现在,Center
允许 ConstrainedBox
达到屏幕可允许的任意大小。 ConstrainedBox
将 constraints
参数带来的约束附加到其子对象上。
Container 必须介于 70 到 150 像素之间。虽然它希望自己有 10 个像素大小, 但最终获得了 70 个像素(最小为 70)。
样例 11
Center(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: Colors.red, width: 1000, height: 1000),
)
)
现在,Center
允许 ConstrainedBox
达到屏幕可允许的任意大小。 ConstrainedBox
将 constraints
参数带来的约束附加到其子对象上。
Container
必须介于 70 到 150 像素之间。 虽然它希望自己有 1000 个像素大小, 但最终获得了 150 个像素(最大为 150)。
样例 12
Center(
child: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 70,
minHeight: 70,
maxWidth: 150,
maxHeight: 150,
),
child: Container(color: Colors.red, width: 100, height: 100),
)
)
现在,Center
允许 ConstrainedBox
达到屏幕可允许的任意大小。 ConstrainedBox
将 constraints
参数带来的约束附加到其子对象上。
Container
必须介于 70 到 150 像素之间。 虽然它希望自己有 100 个像素大小, 因为 100 介于 70 至 150 的范围内,所以最终获得了 100 个像素。
样例 13
UnconstrainedBox(
child: Container(color: Colors.red, width: 20, height: 50),
)
屏幕强制 UnconstrainedBox
变得和屏幕一样大,而 UnconstrainedBox
允许其子级的 Container
可以变为任意大小。
样例 14
UnconstrainedBox(
child: Container(color: Colors.red, width: 4000, height: 50),
)
屏幕强制 UnconstrainedBox
变得和屏幕一样大, 而 UnconstrainedBox
允许其子级的 Container
可以变为任意大小。
不幸的是,在这种情况下,容器的宽度为 4000 像素, 这实在是太大,以至于无法容纳在 UnconstrainedBox
中, 因此 UnconstrainedBox
将显示溢出警告(overflow warning)。
样例 15
OverflowBox(
minWidth: 0.0,
minHeight: 0.0,
maxWidth: double.infinity,
maxHeight: double.infinity,
child: Container(color: Colors.red, width: 4000, height: 50),
);
屏幕强制 OverflowBox
变得和屏幕一样大, 并且 OverflowBox
允许其子容器设置为任意大小。
OverflowBox
与 UnconstrainedBox
类似,但不同的是, 如果其子级超出该空间,它将不会显示任何警告。
在这种情况下,容器的宽度为 4000 像素,并且太大而无法容纳在 OverflowBox
中, 但是 OverflowBox
会全部显示,而不会发出警告。
样例 16
UnconstrainedBox(
child: Container(
color: Colors.red,
width: double.infinity,
height: 100,
)
)
这将不会渲染任何东西,而且你能在控制台看到错误信息。
UnconstrainedBox
让它的子级决定成为任何大小, 但是其子级是一个具有无限大小的 Container
。
Flutter 无法渲染无限大的东西,所以它抛出以下错误: BoxConstraints forces an infinite width.
(盒子约束强制使用了无限的宽度)
样例 17
UnconstrainedBox(
child: LimitedBox(
maxWidth: 100,
child: Container(
color: Colors.red,
width: double.infinity,
height: 100,
)
)
)
这次你就不会遇到报错了。 UnconstrainedBox
给 LimitedBox
一个无限的大小; 但它向其子级传递了最大为 100 的约束。
如果你将 UnconstrainedBox
替换为 Center
, 则LimitedBox
将不再应用其限制(因为其限制仅在获得无限约束时才适用), 并且容器的宽度允许超过 100。
上面的样例解释了 LimitedBox
和 ConstrainedBox
之间的区别。
样例 18
FittedBox(
child: Text(‘Some Example Text.’),
)
屏幕强制 FittedBox
变得和屏幕一样大, 而 Text
则是有一个自然宽度(也被称作 intrinsic 宽度), 它取决于文本数量,字体大小等因素。
FittedBox
让 Text
可以变为任意大小。 但是在 Text
告诉 FittedBox
其大小后, FittedBox
缩放文本直到填满所有可用宽度。
样例 19
Center(
child: FittedBox(
child: Text(‘Some Example Text.’),
)
)
但如果你将 FittedBox
放进 Center
widget 中会发生什么? Center
将会让 FittedBox
能够变为任意大小, 取决于屏幕大小。
FittedBox
然后会根据 Text
调整自己的大小, 然后让 Text
可以变为所需的任意大小, 由于二者具有同一大小,因此不会发生缩放。
样例 20
Center(
child: FittedBox(
child: Text(‘This is some very very very large text that is too big to fit a regular screen in a single line.’),
)
)
然而,如果 FittedBox
位于 Center
中, 但 Text
太大而超出屏幕,会发生什么?
FittedBox 会尝试根据 Text
大小调整大小, 但不能大于屏幕大小。然后假定屏幕大小, 并调整 Text
的大小以使其也适合屏幕。
样例 21
Center(
child: Text(‘This is some very very very large text that is too big to fit a regular screen in a single line.’),
)
然而,如果你删除了 FittedBox
, Text
则会从屏幕上获取其最大宽度, 并在合适的地方换行。
样例 22
FittedBox(
child: Container(
height: 20.0,
width: double.infinity,
)
)
FittedBox
只能在有限制的宽高中 对子 widget 进行缩放(宽度和高度不会变得无限大)。 否则,它将无法渲染任何内容,并且你会在控制台中看到错误。
样例 23
Row(
children:[
Container(color: Colors.red, child: Text(‘Hello!’)),
Container(color: Colors.green, child: Text(‘Goodbye!’)),
]
)
屏幕强制 Row
变得和屏幕一样大,所以 Row
充满屏幕。
和 UnconstrainedBox
一样, Row
也不会对其子代施加任何约束, 而是让它们成为所需的任意大小。 Row
然后将它们并排放置, 任何多余的空间都将保持空白。
样例 24
Row(
children:[
Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’)),
Container(color: Colors.green, child: Text(‘Goodbye!’)),
]
)
由于 Row
不会对其子级施加任何约束, 因此它的 children 很有可能太大 而超出 Row
的可用宽度。在这种情况下, Row
会和 UnconstrainedBox
一样显示溢出警告。
样例 25
Row(
children:[
Expanded(
child: Container(color: Colors.red, child: Text(‘This is a very long text that won’t fit the line.’))
),
Container(color: Colors.green, child: Text(‘Goodbye!’)),
]
)
当 Row
的子级被包裹在了 Expanded
widget 之后, Row
将不会再让其决定自身的宽度了。
取而代之的是,Row
会根据所有 Expanded
的子级 来计算其该有的宽度。
换句话说,一旦你使用 Expanded
, 子级自身的宽度就变得无关紧要,直接会被忽略掉。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
最后
总之啊,家里没矿的同学们,如果你们想以后的日子过得好一些,多想想你们的业余时间怎么安排吧;
技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关
在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。
总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
相信自己,没有做不到的,只有想不到的
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
技术方面的提升肯定是重中之重,但是技术外的一些“软实力”也不能完全忽视,很多时候升职确实是因为你的技术足够强,但也与你的“软实力”密切相关
在这我也分享一份大佬自己收录整理的 Android学习PDF+架构视频+面试文档+源码笔记 ,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料这些都是我闲暇还会反复翻阅并给下属员工学习的精品资料。在脑图中,每个知识点专题都配有相对应的实战项目,可以有效的帮助大家掌握知识点。
总之也是在这里帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
[外链图片转存中…(img-SRU7zbV3-1711931052815)]
[外链图片转存中…(img-G0nahN7a-1711931052815)]
相信自己,没有做不到的,只有想不到的