第五章 容器类
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 协议 ,转载请注明出处!