OverflowBox
对于 OverflowBox ,文档只有一句话:把不同的约束强加给 child,允许 child overflow 父容器。这句话说的太简略了,使用的时候还是一头雾水,代码逻辑是这样的:
BoxConstraints _getInnerConstraints(BoxConstraints constraints) { return BoxConstraints( minWidth: _minWidth ?? constraints.minWidth, maxWidth: _maxWidth ?? constraints.maxWidth, minHeight: _minHeight ?? constraints.minHeight, maxHeight: _maxHeight ?? constraints.maxHeight, ); } @override void performLayout() { if (child != null) { child?.layout(_getInnerConstraints(constraints), parentUsesSize: true); alignChild(); } } 复制代码
用语言描述就是,优先取 OverflowBox 的 minWidth,maxWidth,minHeight,maxHeight,父级的约束值是用来兜底的,这样就清晰多了。parentUsesSize: true
是因为 OverflowBox 有 align 属性,需要摆放 child,比如想把 child 右对齐,如果不知道 child 的 size ,就无法知道 child 左边的 offset 是多少,所以 child 尺寸变化的时候,需要通知 OverflowBox ,让 OverflowBox 重新计算 offset ,调整位置。
OverflowBox 本身的大小是多少呢?下面两段代码给出解答。
@override bool get sizedByParent => true; @override Size computeDryLayout(BoxConstraints constraints) { return constraints.biggest; } 复制代码
sizedByParent
设置为 true
的意思是 OverflowBox 的尺寸只与 constrains 有关,也就是说父级完全可以决定 OverflowBox 的大小。具体是多大呢? constraints.biggest
的意思就是尽可能的大。
OverflowBox 给人的感觉是可以让 child 溢出,但它也可以缩小 child 的活动范围。所以 OverflowBox 的作用就是更改父级的约束。
溢出部分无法响应点击事件
SizedOverflowBox
一个有明确固定尺寸的组件,透传原始约束给子组件,子组件如果比父组件大,就会 overflow。
@override void performLayout() { size = constraints.constrain(_requestedSize); if (child != null) { child!.layout(constraints, parentUsesSize: true); alignChild(); } } 复制代码
constraints.constrain(_requestedSize)
这句的意思就是在 constrains 的允许范围内,取最贴近 _requestedSize 的值。
通过代码可以看出,SizedOverflowBox 的尺寸是受约束和 size 参数共同影响的,也就是说,尺寸必须在约束允许的范围之内。比如约束 50
如果 SizedOverflowBox 的约束是 tight 约束,那么 SizedOverflowBox 就完全失去作用。因为 SizedOverflowBox 和 它的 child 都没有了发挥的空间,都只能一样大。
同样,溢出部分无法响应点击事件
应用场景
虽然这两个组件名字很像,但是效果上大相径庭。
比如实现下面的效果,用 OverflowBox 很合适。
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Container( width: 100, height: 100, color: Colors.green, ), Container( width: 100, height: 100, color: Colors.green, child: OverflowBox( maxWidth: 110, maxHeight: 110, child: Container( width: 110, height: 110, decoration: BoxDecoration(border: Border.all(color: Colors.red)), )), ), Container( width: 100, height: 100, color: Colors.green, ) ]) 复制代码
OverflowBox 的 child 红色 box 溢出 ,但不会影响 Container 的布局,相当于 css 中 outline 的效果。
SizedOverflowBox 有什么应用场景呢?在下图中蓝色的 box 溢出绿色的 box,这种适合用 SizedOverflowBox。
Container( color: Colors.green, alignment: Alignment.topRight, width: 100, height: 100, child: SizedOverflowBox( size: const Size(0, 0), child: Container( width: 20, height: 20, color: Colors.blueAccent, ) ), ) 复制代码
这种效果一般用来做装饰。
OverflowBox 与 SizedOverflowBox 可以实现的效果用其它 widget 也可以实现,不过这两种情况下,用 OverflowBox 与 SizedOverflowBox 可读生更好些。