【Flutter 组件集录】OverflowBox | 8 月更文挑战
前言:
1.认识 OverflowBox 组件
我们都知道,一般布局组件,由于父区域的约束,其子节点区域都会被限制在内父区域之内。但有时我们有需求让子组件脱离区域限制,溢出父区域。而这就是 OverflowBox
的价值所在。源码中的介绍是: 让组件的约束有别于父节点的约束,可以允许组件溢出父部件。
下面是 OverflowBox
组件类的定义
和 构造方法
,可以看出它继承自 SingleChildRenderObjectWidget
。可以设置宽高区域及对其方式。
2. OverflowBox 组件的使用
在说 OverflowBox
之前,先看一下常规的盒约束。如下代码中,父亲 SizedBox
尺寸为 100*100
,按照约束正常的传递,孩子 SizedBox
虽然想要 200*50
区域,但却不能突破父亲约束的显示。如下,第二个 SizedBox
在 100*100
的强约束下,尺寸被定为 100*100
。
class OverflowBoxDemo extends StatelessWidget{
@override
Widget build(BuildContext context) {
return SizedBox(
width: 100,
height: 100,
child: buildBox()
);
}
Widget buildBox() {
return SizedBox(
width: 200,
height: 50,
);
}
}
你如何让子 SizedBox
突破限制呢,如下通过 OverflowBox
设置一个 200*50
的强约束。这样子 SizedBox
则会按照 OverflowBox
施加的约束进行布局。从效果上来看,子 SizedBox
就突破了外层约束的限制。
Widget buildBox() {
return OverflowBox(
minHeight: 50,
minWidth: 200,
maxWidth: 200,
maxHeight: 50,
child: SizedBox(
width: 200,
height: 50,
),
);
}
3.OverflowBox 的 alignment 属性
alignment
代表对齐方式,默认情况下是Alignment.center
,比如上图中,子 SizedBox
是以和外界区域中心对齐的。如下是 Alignment.topLeft
也就是左上角进行对其。
OverflowBox(
alignment: Alignment.topLeft,
minHeight: 50,
minWidth: 200,
maxWidth: 200,
maxHeight: 50,
child: SizedBox(
width: 200,
height: 50,
),
);
Alignment.topCenter
效果如下,也就是说 OverflowBox
不仅可以允许子组件越界,还可以指定子组件相对于外层区域的对齐方式。通过三个方位对比,你应该明白 alignment
的作用了吧。
通过 OverflowBox
组件就可以很容易处理子组件越界的需求,如下,红色组件越出了蓝色区域,大家可以自己试一下。另外说明一点: 通过OverflowBox
越界的部分,无法响应点击事件。
4. OverflowBox 的源码实现
OverflowBox
继承自 SingleChildRenderObjectWidget
,内部维护 RenderConstrainedOverflowBox
对象来实现功能。
实现的原理也很简单,下面红框中的 constraints
是 RenderConstrainedOverflowBox
自身的约束,可以看到在 _getInnerConstraints
中会生成新的约束,如果几个参数都设置了,入参的 constraints
就是无用的,也就说明 RenderConstrainedOverflowBox
其实是忽略了上层约束,用新约束来约束孩子。
打个比方:
---->[场景一]----
孩子: 爸,给我 100 块,买玩具。
父亲: 我只有 50 块,拿去滚蛋。
---->[场景二]----
孩子: 爸,给我 100 块,买玩具。
父亲: 我只有 50 块,拿去滚蛋。
母亲: 别介,我有 100 块, 孩子你拿去吧。
父亲: 孩子他妈,那这 50 你拿着。
可以看出 OverflowBox
的本质就是重新对孩子的区域进行限定
,而脱离 原本约定区域的限定
。但 OverflowBox
本身会是被 原本约定区域限定
。它也算是李代桃僵,成全 child
的 "放肆"。
那本文到这里就结束了,谢谢观看,明天见~
转载自:https://juejin.cn/post/7000285809186177060