多子布局组件 在开发中,我们经常需要将多个Widget放在一起进行布局,比如水平方向、垂直方向排列,甚至有时候需要他们进行层叠,比如图片上面放一段文字等; 这个时候我们需要使用多子布局组件(Multi-child layout widgets)。 比较常用的多子布局组件是Row、Column、Stack。
1. Flex组件 Row
组件和Column
组件都继承自Flex
;
Flex
组件和Row
、Column
属性主要的区别就是多一个 direction
;当direction
的值为Axis.horizontal
的时候,则是Row
,呈一行排布; 当direction
的值为Axis.vertical
的时候,则是Column
,呈一列排布; 它们都有主轴(Main Axis)和交叉轴(Cross Axis)的概念:
2. Row组件 Row({Key key,MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, // 主轴对齐方式MainAxisSize mainAxisSize = MainAxisSize.max, // 水平方向尽可能大CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center, // 交叉处对齐方式TextDirection textDirection, // 水平方向子widget的布局顺序(默认为系统当前Locale环境的文本方向(如中文、英语都是从左往右,而阿拉伯语是从右往左))VerticalDirection verticalDirection = VerticalDirection.down, // 表示Row纵轴(垂直)的对齐方向TextBaseline textBaseline, // 如果上面是baseline对齐方式,那么选择什么模式(有两种可选)List children = const [], })
2.1. mainAxisSize Row的特点:
return RaisedButton(onPressed: (){},color: Colors.red,child: Row(mainAxisSize: MainAxisSize.min,children: [Icon(Icons.favorite),Text("收藏"),],),);
2.2. mainAxisAlignment 元素在Row主轴上的布局方式,它是一个枚举类型:
start
:主轴开始的位置挨个摆放元素;end
:主轴结束的位置挨个摆放元素;center
:主轴的中心点对齐;spaceBetween
: 左右两边的间距为0,其他元素之间平分间距;spaceAround
:左右两边的间距是其他元素的间距的一半;spaceEvenly
:间距平分; class _YZHomeContentState extends State {@overrideWidget build(BuildContext context) {return Row(children: [Container(width: 80, height: 60, color: Colors.red,),Container(width: 120, height: 100, color: Colors.orange,),Container(width: 90, height: 80, color: Colors.blue,),Container(width: 50, height: 50, color: Colors.green,),],mainAxisAlignment: MainAxisAlignment.spaceEvenly,);} }
2.3. CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.end,
元素在Row交叉轴上的布局方式
start
:交叉轴的起始位置对齐;end
:交叉轴的结束位置对齐(垂直方向是包裹内容的);center
:中心点对齐(默认值)baseLine
:基线对齐;(必须有文本才有效果)stretch
: 先将Row占据交叉轴尽可能大的空间,再将所有的子Widget拉伸到最大; 2.4. Expanded 空间分配:拉伸或收缩;
如果控件之间有间隔:拉伸; 如果控件组合宽度超过了屏幕,则压缩; 如上图,间隔等分,如果想把所有间隔分配给第一个; return Row(children: [Expanded(child: Container(width: 80, height: 60, color: Colors.red,),),Container(width: 120, height: 100, color: Colors.orange,),Container(width: 90, height: 80, color: Colors.blue,),Container(width: 50, height: 50, color: Colors.green,),],mainAxisAlignment: MainAxisAlignment.spaceEvenly,crossAxisAlignment: CrossAxisAlignment.end,);} }
效果:
第一个控件宽度做了拉伸; 2.4.1 flex
作用 Expanded(flex: 1,child: Container(width: 80, height: 60, color: Colors.red,),), Expanded(flex: 2,child: Container(width: 40, height: 60, color: Colors.green,),),
剩余空间分配比例: 当有多个Expanded
时,
如果flex相等,则拉伸的宽度相同; 如果flex不等,按比例拉伸,如上面flex:2
控件的宽度拉伸为flex: 1
宽度的2倍,原来的width
数值不再起作用。 3. Column组件 同Row;
4. Stack组件 在开发中,我们多个组件很有可能需要重叠显示,比如在一张图片上显示文字或者一个按钮等。在Flutter中我们需要使用层叠布局Stack。
4.1 Stack介绍 Stack的大小默认是包裹内容的.
alignment:从什么位置开始排布所有的子Widget; fit: expand 将子元素拉伸到尽可能大; overflow:超出部分如何处理; Stack({Key key,this.alignment = AlignmentDirectional.topStart,this.textDirection,this.fit = StackFit.loose,this.overflow = Overflow.clip,this.clipBehavior = Clip.hardEdge,List children = const [],})
4.2 示例 class _YZHomeContentState extends State {@overrideWidget build(BuildContext context) {return Stack(alignment: AlignmentDirectional.bottomCenter,overflow: Overflow.visible,children: [Image.asset("assets/images/image_01.png",),Container(width: 150, height: 50, color: Colors.red,),// Positioned( //文字在Stack内部相对布局调整// right: 10,// bottom: 20,// child:Text("这是图片上的文字"),// ),],);} }
class _YZHomeContentState extends State {bool _isFavor = false;@overrideWidget build(BuildContext context) {return Stack(children: [Image.asset("assets/images/image_02.jpeg?s=#34;,width: MediaQuery.of(context).size.width,),Positioned(left: 0,right: 0,bottom: 0,child: Container(padding: EdgeInsets.all(8),color: Color.fromARGB(10, 0, 0, 0),child: Row(mainAxisAlignment: MainAxisAlignment.spaceBetween,children: [Text("这是图片上的文字描述", style: TextStyle(fontSize: 15, color: Colors.red),),IconButton(icon: Icon(Icons.favorite,color: _isFavor ? Colors.red : Colors.white,),onPressed: () {setState(() {_isFavor = !_isFavor;});}),],),),),],);} }