线性布局
横向线性布局
Row可以在水平方向排列其子组件
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Row(
///表示水平方向子组件的布局顺序(是从左往右还是从右往左),默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左)。
textDirection: TextDirection.ltr,
///表示在水平方向占用的空间,默认是MainAxisSize.max
mainAxisSize: MainAxisSize.max,
///表示子组件在Row所占用的水平空间内对齐方式,
///如果mainAxisSize值为MainAxisSize.min,则此属性无意义。
///只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义,
///MainAxisAlignment.start表示沿textDirection的初始方向对齐,
///如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
///盒子
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 200,
height: 200,
color: Colors.blue,
),
],
));
}
}
竖向线性布局
Column可以在垂直方向排列其子组件
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Column(
///表示子组件在纵轴方向的对齐方式,Row的高度等于子组件中最高的子元素高度,它的取值和MainAxisAlignment一样(包含start、end、 center三个值),
///不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;
///而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
///盒子
Container(
width: 100,
height: 100,
color: Colors.red,
),
Container(
width: 200,
height: 200,
color: Colors.blue,
),
],
));
}
}
弹性布局
弹性布局允许子组件按照一定比例来分配父容器空间。Flutter中的弹性布局主要通过Flex和Expanded来配合实现。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Flex(
//必须指定方向
direction: Axis.vertical,
children: [
Expanded(
//占比
flex: 1,
child: Container(
color: Colors.red,
)),
//配合Flex使用
Expanded(
flex: 1,
child: Container(
color: Colors.blue,
)),
Expanded(
flex: 1,
child: Container(
color: Colors.yellow,
)),
],
));
}
}
定位
类似Android中的FrameLayout布局,子组件可以根据距父容器四个角的位置来确定自身的位置。Flutter中使用Stack和Positioned这两个组件来配合实现绝对定位。Stack允许子组件堆叠,而Positioned用于根据Stack的四个角来确定子组件的位置。
Stack属性
alignment:此参数决定如何去对齐没有定位(没有使用Positioned)或部分定位的子组件。所谓部分定位,在这里特指没有在某一个轴上定位:left、right为横轴,top、bottom为纵轴,只要包含某个轴上的一个定位属性就算在该轴上有定位。textDirection:和Row、Wrap的textDirection功能一样,都用于确定alignment对齐的参考系,即: textDirection的值为TextDirection.ltr,则alignment的start代表左,end代表右,即从左往右的顺序;textDirection的值为TextDirection.rtl,则alignment的start代表右,end代表左,即从右往左的顺序。fit:此参数用于确定没有定位的子组件如何去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示扩伸到Stack的大小。overflow:此属性决定如何显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被剪裁(隐藏),值为Overflow.visible 时则不会。
Positioned属性
left、top 、right、 bottom分别代表离Stack左、上、右、底四边的距离
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SizedBox(
width: 400,
height: 400,
child: Stack(
children: [
Positioned(
right: 50,
bottom: 50,
child: Container(
width: 100,
height: 100,
color: Colors.red,
)),
Positioned(
left: 100,
top: 100,
child: Container(
width: 200,
height: 200,
color: Colors.blue,
))
],
),
));
}
}
流式布局
在使用Row和Colum时,如果子widget超出屏幕范围,则会报溢出错误。Flutter中通过Wrap和Flow来支持流式布局,溢出部分则会自动折行,
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Wrap(
//水平间距
spacing: 20,
//垂直间距
runSpacing: 10,
//对齐方式
alignment: WrapAlignment.center,
children: [
Container(
width: 150,
height: 150,
color: Colors.red,
),
Container(
width: 150,
height: 150,
color: Colors.blue,
),
Container(
width: 150,
height: 150,
color: Colors.yellow,
)
],
));
}
}
由于Flow使用起来比较麻烦,一般不用,就不介绍啦~~