第五章 容器类
5.1 填充(Padding)
Padding可以给其子节点添加填充(留白),和边距效果类似。我们在前面很多示例中都已经使用过它了,现在来看看它的定义:
Padding({
...
EdgeInsetsGeometry padding,
Widget child,
})
EdgeInsetsGeometry是一个抽象类,开发中,我们一般都使用EdgeInsets类,它是EdgeInsetsGeometry的一个子类,定义了一些设置填充的便捷方法。
fromLTRB(double left, double top, double right, double bottom):分别指定四个方向的填充。all(double value): 所有方向均使用相同数值的填充。only({left, top, right ,bottom }):可以设置具体某个方向的填充(可以同时指定多个方向)。symmetric({ vertical, horizontal }):用于设置对称方向的填充,vertical指top和bottom,horizontal指left和right。
容器可以容纳布局
5.2 尺寸限制类容器
尺寸限制类容器用于限制容器大小,Flutter中提供了多种这样的容器,如ConstrainedBox、SizedBox、UnconstrainedBox、AspectRatio等,本节将介绍一些常用的。
5.2.1 ConstrainedBox
ConstrainedBox用于对子组件添加额外的约束。例如,如果你想让子组件的最小高度是80像素,你可以使用const BoxConstraints(minHeight: 80.0)作为子组件的约束。
5.2.2 SizedBox
SizedBox用于给子元素指定固定的宽高,如:
SizedBox(
width: 80.0,
height: 80.0,
child: redBox
)
运行效果如图5-3所示:

实际上SizedBox只是ConstrainedBox的一个定制,上面代码等价于:
5.2.3 多重限制
如果某一个组件有多个父级ConstrainedBox限制,那么最终会是哪个生效?
对于minWidth和minHeight来说,是取父子中相应数值较大的。
思考题:对于maxWidth和maxHeight,多重限制的策略是什么样的呢?
5.2.4 UnconstrainedBox
UnconstrainedBox不会对子组件产生任何限制,它允许其子组件按照其本身大小绘制。一般情况下,我们会很少直接使用此组件,但在”去除”多重限制的时候也许会有帮助
5.2.5 其它尺寸限制类容器
除了上面介绍的这些常用的尺寸限制类容器外,还有一些其他的尺寸限制类容器,比如AspectRatio,它可以指定子组件的长宽比、LimitedBox 用于指定最大宽高、FractionallySizedBox 可以根据父容器宽高的百分比来设置子组件宽高等
5.3 装饰容器DecoratedBox
DecoratedBox可以在其子组件绘制前(或后)绘制一些装饰(Decoration),如背景、边框、渐变等。DecoratedBox定义如下:
const DecoratedBox({
Decoration decoration,
DecorationPosition position = DecorationPosition.background,
Widget child
})
decoration:代表将要绘制的装饰,它的类型为Decoration。Decoration是一个抽象类,它定义了一个接口createBoxPainter(),子类的主要职责是需要通过实现它来创建一个画笔,该画笔用于绘制装饰。position
Decoration:此属性决定在哪里绘制
DecorationPosition,它接收的枚举类型,该枚举类有两个值: - `background`:在子组件之后绘制,即背景装饰。 - `foreground`:在子组件之上绘制,即前景。 # 5.5 Container 我们在前面的章节示例中多次用到过`Container`组件,本节我们就详细介绍一下`Container`组件。`Container`是一个组合类容器,它本身不对应具体的`RenderObject`,它是`DecoratedBox`、`ConstrainedBox、Transform`、`Padding`、`Align`等组件组合的一个多功能容器,所以我们只需通过一个`Container`组件可以实现同时需要装饰、变换、限制的场景。下面是`Container`的定义: ```dart Container({ this.alignment, this.padding, //容器内补白,属于decoration的装饰范围 Color color, // 背景色 Decoration decoration, // 背景装饰 Decoration foregroundDecoration, //前景装饰 double width,//容器的宽度 double height, //容器的高度 BoxConstraints constraints, //容器大小的限制条件 this.margin,//容器外补白,不属于decoration的装饰范围 this.transform, //变换 this.child, })
Container的大多数属性在介绍其它容器时都已经介绍过了,不再赘述,但有两点需要说明:
- 容器的大小可以通过
width、height属性来指定,也可以通过constraints来指定;如果它们同时存在时,width、height优先。实际上Container内部会根据width、height来生成一个constraints。 color和decoration是互斥的,如果同时设置它们则会报错!实际上,当指定color时,Container内会自动创建一个decoration。
实例
我们通过Container来实现如图5-16所示的卡片:

实现代码如下:
Container(
margin: EdgeInsets.only(top: 50.0, left: 120.0), //容器外填充
constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0), //卡片大小
decoration: BoxDecoration(//背景装饰
gradient: RadialGradient( //背景径向渐变
colors: [Colors.red, Colors.orange],
center: Alignment.topLeft,
radius: .98
),
boxShadow: [ //卡片阴影
BoxShadow(
color: Colors.black54,
offset: Offset(2.0, 2.0),
blurRadius: 4.0
)
]
),
transform: Matrix4.rotationZ(.2), //卡片倾斜变换
alignment: Alignment.center, //卡片内文字居中
child: Text( //卡片文字
"5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),
),
);
可以看到Container具备多种组件的功能,通过查看Container源码,我们会很容易发现它正是前面我们介绍过的多种组件组合而成。在Flutter中,Container组件也正是组合优先于继承的实例。
Padding和Margin
接下来我们来研究一下Container组件margin和padding属性的区别:
...
Container(
margin: EdgeInsets.all(20.0), //容器外补白
color: Colors.orange,
child: Text("Hello world!"),
),
Container(
padding: EdgeInsets.all(20.0), //容器内补白
color: Colors.orange,
child: Text("Hello world!"),
),
...

可以发现,直观的感觉就是margin的留白是在容器外部,而padding的留白是在容器内部,读者需要记住这个差异。事实上,Container内margin和padding都是通过Padding 组件来实现的,上面的示例代码实际上等价于:
...
Padding(
padding: EdgeInsets.all(20.0),
child: DecoratedBox(
decoration: BoxDecoration(color: Colors.orange),
child: Text("Hello world!"),
),
),
DecoratedBox(
decoration: BoxDecoration(color: Colors.orange),
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Text("Hello world!"),
),
),
...
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!