- Flutter中,布局方式为
弹性盒子布局
- 可以将一个一个Widget看做一个一个矩形盒子,盒子套盒子模式
1.Container
如果没有设置child,Container大小与上层一致
如果设置了child,大小与child大小一致
-
alignment(x,y)
,值范围从-1.0到1.0。设置子部件对齐方式。如果当前Container上层大小确定,设置alignment后,Container大小不受child大小影响
- alignment(-1,-1),左上角。等于Alignment.topLeft
- alignment(0,0),中间。等于Alignment.center
- alignment(1,1),右下角。等于Alignment.bottomRight
class ContainerDemo extends StatelessWidget {
const ContainerDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
child: Container(
width: 200,
height: 200,
color: Colors.red,
),
alignment: Alignment.center, //设置后,不受child影响
);
}
}
layout_container.png
|
layout_container_alignment.png
|
2.Flex
- Row、Column的父类
- 可以沿着水平或垂直方向排列子Widget
-
direction
,必填参数,排列方向
class FlexDemo extends StatelessWidget {
const FlexDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
child: Flex(
direction: Axis.horizontal,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
),
);
}
}
laout_flex_horizontal
|
laout_flex_vertical
|
3.主轴
- 类型为
MainAxisAlignment
- 横向布局,默认方向为
由左向右
- 纵向布局,默认方向为
由上到下
-
start
- 主轴最开始地方,默认值
-
center
- 主轴中间地方
-
end
- 主轴结束地方
-
spaceBottom
- 小组件间的间距的平均分布
-
spaceAround
- 小组件间周围平均分布
-
spaceEvenly
- 小组件均匀分布
class FlexDemo extends StatelessWidget {
const FlexDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
alignment: Alignment.center,
child: Flex(
mainAxisAlignment: MainAxisAlignment.spaceAround,
direction: Axis.horizontal,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
),
);
}
}
flex_mainAxisAlignment_start.png
|
flex_mainAxisAlignment_center.png
|
flex_mainAxisAlignment_end.png
|
flex_mainAxisAlignment_spaceBetween.png
|
flex_mainAxisAlignment_spaceAround.png
|
flex_mainAxisAlignments_paceEvenly.png
|
4.交叉轴
- 类型为
MainAxisAlignment
-
start
- 交叉轴最开始地方
-
center
- 交叉轴中间地方,默认值
-
end
- 交叉轴结束地方
-
stretch
- 交叉轴方向拉伸满
-
spaceAround
- 小组件间周围平均分布
-
baseLIne
- 基准线。当direction: Axis.horizontal
时,多个小部件为Text时,基于文字对齐。英文alphabetic
其他语言ideographic
。注意这里只有设置了textBaseLine才能设置,否则会报错
class FlexBaselineDemo extends StatelessWidget {
const FlexBaselineDemo({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
alignment: Alignment.center,
child: Flex(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.baseline,
/*
* TextBaseLine
* alphabetic,英文
* ideographic,其他语言
* 测试完感觉2者在中文/英文来用任意一个都差不多
* */
textBaseline: TextBaseline.ideographic,
direction: Axis.horizontal,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(
aspectRatio: 1,
child: Center(
child: Text("红色", style: TextStyle(fontSize: 15, color: Colors.white),),
),
),
),
Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(
aspectRatio: 1,
child: Center(
child: Text("蓝色", style: TextStyle(fontSize: 20, color: Colors.white),),
),
),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(
aspectRatio: 1,
child: Center(
child: Text("黄色", style: TextStyle(fontSize: 30, color: Colors.white),),
),
),
),
],
),
);
}
}
flex_crossAxisAlignment_start.png
|
flex_crossAxisAlignment_center.png
|
flex_crossAxisAlignment_end.png
|
flex_crossAxisAlignment_stretch.png
|
flex_crossAxisAlignment_baseline_ideographic.png
|
flex_crossAxisAlignment_baseline_alphabetic.png
|
5.Row、Column
- Row、Column继承Flex
- Row相当于Flex中
direction: Axis.horizontal
- Column相当于Flex中
direction: Axis.vertical
- 使用方式与Flex一致
- 注意:textDirection设置后可以改变主轴方向,仅在Row上改变主轴方向
class RowOrColumnDemo extends StatelessWidget {
final bool isRow;
const RowOrColumnDemo(this.isRow);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
alignment: Alignment.center,
child: isRow ? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
) :
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
) ,
);
}
}
6.Stack
- 视图叠着排列,z方向
- 方向,
由里到外
- 一般设置alignment来设置子部件显示的位置
- 需要设置宽高或依赖子部件宽高撑大
-
Positioned
,在Stack下也可以使用Positioned来设置小部件位置
class StackDemo extends StatelessWidget {
final bool isShowPositioned;
const StackDemo(this.isShowPositioned);
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height - kToolbarHeight - _statusBarHeight,
child: Stack(
alignment: Alignment.center,
children: [
Container(
width: 200,
height: 200,
color: Colors.red,
),
Container(
width: 150,
height: 150,
color: Colors.blue,
),
Container(
width: 100,
height: 100,
color: Colors.yellow,
),
if (isShowPositioned) Positioned(
right: 0,
width: 50,
height: 150,
top: 150,
child: Container(
color: Colors.purple,
)),
],
),
);
}
}
stack_normal.png
|
stack_positioned.png
|
7. AspectRatio
- 设置当前部件的宽高比。注意只会影响当前部件,不会影响子部件
- 当父部件宽高都已经设置后,设置的宽高比失效
Container(
width: 200,
height: 150,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,), //失效
)
8.Expanded
- 在主轴上不会剩余间隙,将会被Expanded拉伸。设置后,主轴小部件之间间距将变为0
-
flex
为弹性系数,系数越大拉伸的距离占比越大。主轴方向下的所有Expanded按照其flex的比例来分割全部的空闲空间
- 这里使用Row来演示
class ExpandedDemo extends StatelessWidget {
final bool isRow;
const ExpandedDemo({required this.isRow});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.grey[400],
alignment: Alignment.center,
child: isRow ? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Expanded( //蓝色在主轴上填满
child: Container(
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
) :
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
width: 60,
color: Colors.red,
child: const AspectRatio(aspectRatio: 1,),
),
Expanded( //蓝色在主轴上填满
child: Container(
width: 80,
color: Colors.blue,
child: const AspectRatio(aspectRatio: 1,),
),
),
Container(
width: 100,
color: Colors.yellow,
child: const AspectRatio(aspectRatio: 1,),
),
],
) ,
);
}
}
row_expanded.png
|
column_expanded.png
|
9.margin&padding
-
margin
,外边距。影响当前部件的内容边距
-
padding
,内边距。影响当前子部件的内容边距