Flutter组件之Container

简介

A convenience widget that combines common painting, positioning, and sizing widgets.

一般我们会在将这个组件用于设置widget的背景样式,限制尺寸或者形状。Container可以帮助我们组合、装饰和定位子widget。

如果将widget包装在无参的container中,其外观不会发生任何变化

如果没有其他内容,container将根据其子容器自行调整大小

属性

Container({
Key key, //唯一标识符
this.alignment, //child的对齐方式
this.padding, //padding(容器内间隔,属于decoration作用区域)
Color color, //container背景色
Decoration decoration, //背景装饰
this.foregroundDecoration, //前景装饰
double width, //容器宽度
double height, //容器宽度
BoxConstraints constraints, //容器大小的限制条件
this.margin, //容器(外间隔,不属于decoration作用区域)
this.transform, //变换矩阵(Matrix4类型)
this.child, //Container中的子widget
})

容器大小可以通过width和height来进行指定,也可以通过constraints来指定,同时存在以width和height优先,另外color和decoration也是互斥的

举个例子

class MyContainerDemo extends StatelessWidget {
final String title;

MyContainerDemo({Key key, this.title}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
border: new Border.all(
color: Colors.blue,
width: 8,
),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Text(
'Container',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 28),
),
),
),
);
}
}
image-20210131191139320.png

Child

如果Container里面没有子控件,它就会填充整个屏幕;如果有子控件,Container就会自动适应子控件大小,Container只能容纳一个子控件

Alignment

Alignment属性主要有以下几个属性:Alignment、FractionalOffset、AlignmentDirectional。此属性是针对于Container内部的各个子控件的布局

举个例子,我在上面的demo中加入了alignment: Alignment.bottomCenter,可以看到Text控件的位置发生了变化

class MyContainerDemo extends StatelessWidget {
final String title;

MyContainerDemo({Key key, this.title}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
border: new Border.all(
color: Colors.blue,
width: 8,
),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Text(
'Container',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 28),
),
alignment: Alignment.bottomCenter,
),
),
);
}
}
image-20210131214806326.png

Alignment有很多的属性,为了方便理解他们的一个位置,我们可以画以下的一个图

Flutter--widget--container.png
  • Alignment.bottomCenter 对应 Alignment(0.0, 1.0)
  • Alignment.bottomLeft 对应 Alignment(-1.0, 1.0)
  • Alignment.bottomRight 对应 Alignment(1.0, 1.0)
  • Alignment.center 对应 Alignment(0.0, 0.0)
  • Alignment.centerLeft 对应 Alignment(-1.0, 0.0)
  • Alignment.centerRight 对应 Alignment(1.0, 0.0)
  • Alignment.topCenter 对应 Alignment(0.0, -1.0)
  • Alignment.topLeft 对应 Alignment(-1.0, -1.0)
  • Alignment.topRight 对应 Alignment(1.0, -1.0)

除了直接使用类似于Alignment.topCenter这样的预制属性外,我们也可以使用Alignment将控件放在其他位置

FractionalOffset的坐标轴如下图

Flutter--widget--container-FractionalOffset坐标系图.png
  • FractionalOffset.bottomCenter 对应 FractionalOffset(0.5, 1.0)
  • FractionalOffset.bottomLeft 对应 FractionalOffset(0.0, 1.0)
  • FractionalOffset.bottomRight 对应 FractionalOffset(1.0, 1.0)
  • FractionalOffset.center 对应 FractionalOffset(0.5, 0.5)
  • FractionalOffset.centerLeft 对应 FractionalOffset(0.0, 0.5)
  • FractionalOffset.centerRight 对应 FractionalOffset(1.0, 0.5)
  • FractionalOffset.topCenter 对应 FractionalOffset(0.5, 0.0)
  • FractionalOffset.topLeft 对应 FractionalOffset(0.0, 0.0)
  • FractionalOffset.topRight 对应 FractionalOffset(1.0, 0.0)

AlignmentDirectional 的坐标轴如下图

Flutter--widget--container-AlignmentDirectional 坐标系图.png
  • AlignmentDirectional.bottomCenter 对应 AlignmentDirectional(0.0, 1.0)
  • AlignmentDirectional.bottomEnd 对应 AlignmentDirectional(1.0, 1.0)
  • AlignmentDirectional.bottomStart 对应 AlignmentDirectional(-1.0, 1.0)
  • AlignmentDirectional.center 对应 AlignmentDirectional(0.0, 0.0)
  • AlignmentDirectional.centerEnd 对应 AlignmentDirectional(1.0, 0.0)
  • AlignmentDirectional.centerStart 对应 AlignmentDirectional(-1.0, 0.0)
  • AlignmentDirectional.topCenter 对应 AlignmentDirectional(0.0, -1.0)
  • AlignmentDirectional.topEnd 对应 AlignmentDirectional(1.0, -1.0)
  • AlignmentDirectional.topStart 对应 AlignmentDirectional(-1.0, -1.0)

Margin

Margin是指相邻的两个或者多个控件之间的距离,主要有以下几种方法

  • EdgeInsets.all()
  • EdgeInsets.symmetric()
  • EdgeInsets.fromLTRB()
  • EdgeInsets.only()

EdgeInsets.all()

主要用于添加四周约束,上下左右的Margin值一致

//EdgeInsets.all()
class MarginPropertyEdgeInsetsAllWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.white,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.green,
margin: EdgeInsets.all(200),
),
),
);
}
}

实现效果如下:

image-20210221001916370.png

EdgeInsets.symmetric()

主要用于添加垂直方向的约束

//EdgeInsets.all()
class MarginPropertyEdgeInsetsSymmetricWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.white,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.green,
margin: EdgeInsets.symmetric(vertical: 50, horizontal: 50),
),
),
);
}
}
image-20210221002129779.png

EdgeInsets.fromLTRB()

主要用于添加left、top、right、bottom四个方向的约束

//EdgeInsets.fromLTRB()
class MarginPropertyEdgeInsetsFromLTRBWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.white,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.green,
margin: EdgeInsets.fromLTRB(5, 50, 100, 100),
),
),
);
}
}
image-20210221002452786.png

EdgeInsets.only()

用于约束哪些方向上的margin是非0的,不设置值默认为0

//EdgeInsets.only()
class MarginPropertyEdgeInsetsOnlyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
color: Colors.white,
alignment: AlignmentDirectional(0.0, 0.0),
child: Container(
color: Colors.green,
margin: EdgeInsets.only(),
),
),
);
}
}

在这个例子中 ,我们四个方向都没有设置值,那么它四个方向的默认值都是0

image-20210221002623791.png

Padding

既然有了Margin,那么怎么能少了Padding,不同之处在于Padding主要是设置主控件内部子控件之间的间距,举个例子:

class MyContainerDemo extends StatelessWidget {
final String title;

MyContainerDemo({Key key, this.title}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
border: new Border.all(
color: Colors.blue,
width: 8,
),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Text(
'Container',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 28),
),
// alignment: Alignment.bottomCenter,
padding: EdgeInsets.all(50),
),
),
);
}
}

效果就是这样的

image-20210221112945025.png

Transform

Container中的Transform属性可以通过使用不同的Matrix从而实现多种多样的变化,举个例子:

class MyContainerDemo extends StatelessWidget {
final String title;

MyContainerDemo({Key key, this.title}) : super(key: key);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Center(
child: Container(
width: 300,
height: 300,
decoration: BoxDecoration(
color: Colors.white,
border: new Border.all(
color: Colors.blue,
width: 8,
),
borderRadius: const BorderRadius.all(const Radius.circular(8)),
),
child: Text(
'Container',
textAlign: TextAlign.center,
style: TextStyle(fontSize: 28),
),
alignment: Alignment.bottomCenter,
transform: Matrix4.rotationY(0.5),
),
),
);
}
}

变换前和变换后的效果对比如下:

image-20210221000642997.png