[toc]
拥有单个子元素的布局 widget
Padding
包裹子 widget 为其添加间距,Padding Widget 的大小是 child 的大小加上 padding。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("PaddingWidget"),),
body: Padding(
// padding: const EdgeInsets.all(20),// 上左下右 padding 都是 20
padding: const EdgeInsets.only(left: 20,top: 50,right: 80,bottom: 100),//分别设置
child: Text("Content"),
),
),
);
}
Center
将 child 放在垂直水平都居中的位置显示。如果没有指定 Center Widget 的大小,那么它就会尽可能的大,类似 match_parent 。如果指定 widthFactor 和 heightFactor 那么它的大小就根据指定的值来设定。例如:widthFactor 指定为 2.0, Center Widget 的宽为 child 宽的 2 倍。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("PaddingWidget"),),
body: Center(
widthFactor: 2.0,// 宽度为 child 宽的 2 倍
heightFactor: 2.0,
child: Container(
width: 100, // 指定宽度为 100
height: 100,
color: Colors.pinkAccent,
),
),
),
);
}
Align
将子 widget 根据指定的对齐方式放置在 Align Widget 中,Align Widget 大小计算方式与 Center Widget 相同。
对齐方式 AlignmentGeometry 类型参数可以通过三种方式设置
- Alignment 的常量。如:Alignment.topRight 于 Align Widget 上右对齐
- Alignment 构造。以 Align Widget 为中心为原点(0,0),参数 x 是 0.5 * child 宽的倍数。y 是 0.5 * child 高的倍数。x 和 y 的取值范围为[-1,1]。
- FractionalOffset。以 Align Widget 的左顶点为原点(0,0),参数 x 是 child 宽的倍数。y 是 child 高的倍数。x 和 y 的取值范围为[0,1]。
Widget build(BuildContext context) {
TextStyle txtStyle = TextStyle( //文本样式
fontWeight: FontWeight.bold,
fontSize: 18.0,
);
Widget getAlignWidthAlign(AlignmentGeometry align,Color childColor){
return Align(
widthFactor: 2.0,
heightFactor: 2.0,
alignment: align,
child: Container(
width: 50,
height: 50,
color: childColor,
),
);
}
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("AlignWidget"),),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.all(20),
child: Text("Const" ,style: txtStyle,),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
getAlignWidthAlign(Alignment.topLeft, Colors.pinkAccent),
getAlignWidthAlign(Alignment.center, Colors.lightBlueAccent),
getAlignWidthAlign(Alignment.bottomRight, Colors.lightGreenAccent)
],
),
Padding(
padding: const EdgeInsets.all(20),
child: Text("Alignment Constructors" ,style: txtStyle,),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// 原点 即 center
getAlignWidthAlign(Alignment(0, 0), Colors.pinkAccent),
//参数是二分之一 child 宽高的倍数
// 从中心点向右移动 child 宽度的一半 ,向下移动 child 高度的一半 ,即 rightBottom
getAlignWidthAlign(Alignment(1, 1), Colors.lightBlueAccent),
getAlignWidthAlign(Alignment(-1, -1), Colors.lightGreenAccent)
],
),
Padding(
padding: const EdgeInsets.all(20),
child: Text("FractionalOffset" ,style: txtStyle,),
),
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
//参数是 child 宽高的倍数
//原点 即 leftTop
getAlignWidthAlign(FractionalOffset(0, 0), Colors.pinkAccent),
//向右移动 child 宽度和高度的 0.5 倍,即 center
getAlignWidthAlign(FractionalOffset(0.5, 0.5), Colors.lightBlueAccent),
getAlignWidthAlign(FractionalOffset(1, 1), Colors.lightGreenAccent)
],
),
],
),
),
);
}
ConstrainedBox
为 child 添加一个 ConstrainedBox 约束来指定 child 的 minWidth、minHeight、maxWidth、maxHeight。 child 的最终尺寸由 child 的原始 尺寸和约束同时决定,例如 child 宽为 x :
- x < minWidth => minWidth
- x > maxWidth => maxWidth
- minWidth < x < maxWidth => x
高同理。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("ConstrainedBox Demo"),),
body: ConstrainedBox(
constraints: BoxConstraints(
minWidth: 50,
minHeight: 50,
maxWidth: 200,
maxHeight: 200,
),
child: Container(
width: 100, // 指定宽度为 100
height: 100,
color: Colors.pinkAccent,
),
),
),
);
}
Transform
为 child 添加平移(translate)、缩放(scale)、旋转(rotate)三种转变。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Transform Widget"),),
body: Transform.translate(// translate 平移
//offset x 轴方向平移 100, y 轴方向平移100
offset: Offset(100, 100),
child: Container(
width: 100, // 指定宽度为 100
height: 100,
color: Colors.pinkAccent,
),
),
),
);
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("Transform Widget"),),
body: Center(
child: Transform.rotate(
//origin 旋转的中心点,默认 child 中点
origin: Offset(0, 100), //原点向下移动 100 即底边中点
angle: 45,//顺时针旋转 45度
child: Container(
width: 100, // 指定宽度为 100
height: 200,
color: Colors.pinkAccent,
),
),
),
),
);
}
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar( title: Text("Transform Widget"), ),
body: Center(
child: Transform.scale(
//缩放 倍数
scale: 2,
// 默认缩放中点是 child 中点,即 center
//alignment 和 origin 可以改变缩放中点
alignment: Alignment.topRight,//缩放中点为右顶点
origin: Offset(-50, 100),// 将缩放中点左移 50 下移100
child: Container(
width: 100, // 指定宽度为 100
height: 200,
color: Colors.pinkAccent,
),
),
)),
);
}
alignment 和 origin 同时存在时缩放中点定位先计算 alignment 再计算 origin。有趣的是当 origin 的 offset 移动超过了 child 的范围时,offset 对缩放中点的影响并不是原来的 x 轴 正右负左,y轴 正下负上。
如图 4 ,alignment 为右顶点,offset(50,100) 此时向右移动超出 child 的范围,x 轴的移动变成了 向左移动 150 (child宽(100) + 50)。
Container
作为最常用的拥有单个子元素的布局 widget,首先 Container 会尽可能的大,类似 match_parent。然后它整合了上面介绍的 widget 功能,可以同时添加 padding、margin、constraints、transform,还可添加 decoration 装饰。
BoxDecoration 盒装饰可以添加边框、边框圆角、背景颜色、背景图片等。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Container'),
),
body: Container(
width: 300,
height: 300,// 宽高
constraints: BoxConstraints.loose(Size(200, 200)),//约束 Container 宽高不能超过 200
alignment: Alignment.bottomRight,// Container 中 child 的对齐为右下
margin: const EdgeInsets.all(30.0),// Container 边距
padding: const EdgeInsets.all(20.0),// Container 距 child 的间距
decoration: BoxDecoration(
border: Border.all( // Container 的边框
color: Colors.red,
width: 15.0
),
//shape: BoxShape.circle,//shape 为 circle 时不能设置 borderRadius
// color: Colors.yellow[300], //Container 背景颜色
borderRadius: const BorderRadius.all(const Radius.circular(30.0)) // 边框圆角
),
transform: Matrix4.translationValues(50, 50, 0),// Container 平移
child: Container(
width: 100, // 指定宽度为 100
height: 100,
color: Colors.pinkAccent,
)
),
),
);
}
FittedBox
根据缩放选项(fit)对child 进行缩放,还可以利用 对齐(alignment)来设置 child 的位置。
BoxFit 的枚举值如下,Image 也是用这些枚举值来控制缩放的。
缩放选项 | 说明 | 效果 |
---|---|---|
BoxFit.contain | 等比缩放,显示的尽可能大 |
|
BoxFit.cover | 尽可能小,但仍覆盖整个 box |
|
BoxFit.fill | 不考虑缩放比例,单纯填满整个 box |
|
BoxFit.fitHeight | 等比缩放,使 child 的高和 box 一致 |
|
BoxFit.fitWidth | 宽一致 |
|
BoxFit.none | 啥都不做 |
|
BoxFit.scaleDown | 等比将 child 缩小到 box 可以装下它,如果 box 原本就可以装下它就啥都不做 |
|
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("FittedBoxWidget"),),
body:Container(
width: 200,
height: 200,
child: FittedBox(
fit: BoxFit.fitWidth,//适应宽度
alignment: Alignment.topCenter,//上中对齐
child: Container(
width: 100, // 指定宽度为 100
height: 50,
color: Colors.pinkAccent,
),
),
),
),
);
}
AspectRatio
按照指定的宽高比设置 child 的大小
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("AspectRatioWidget"),
),
body: Container(
// AspectRatio 的 parent 不能指定宽度。
// 指定宽度后 aspectRatio 失效,怎么设置都会填满 parent
height: 300,
child: AspectRatio(
aspectRatio: 0.5,// 宽高比 1 / 2
child: Container( // AspectRatio 的 child 指定宽高无效
width: 1,
height: 1,
color: Colors.pinkAccent,
),
),
),
),
);
}
Baseline
设置一条基线,使 child 根据基线类型与基线对齐。
基线类型(baselineType)
- TextBaseline.alphabetic :文字底部 , 例如 good 即 g 的底部
- TextBaseline.ideographic : 文字基线
baselineType 当child 是 Text 时 生效, 如果不是 Text ,则 child 的底部跟 基线对齐。
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("BaselineWidget"),
),
body: Container(
width: 200,
height: 200,
margin: const EdgeInsets.all(20),
child: Baseline(
//基线位置
baseline: 90,
//child 是 Text 时 生效; 如果不是 Text ,则 child 的底部跟 基线对齐
baselineType: TextBaseline.ideographic,
child: Container(
width: 100,
height: 100,
color: Colors.pinkAccent,
),
),
),
),
);
}