前几篇博客,我们主要讲了Flutter中的基本组件,那么,我们这边博客就来讲一下Flutter中的页面布局。
页面布局包括基础布局处理、宽高尺寸处理、列表及表格布局、其他布局处理等。
主要包括:Container(容器布局),Center(居中布局),Padding(填充布局),Align(对齐布局),Column(垂直布局),Row(水平布局),Expanded(配合Column,Row使用),FittedBox(缩放布局),Stack(层叠布局),OverflowBox(溢出父视图容器)。
Container(容器布局)是一个组合Widget,内部有绘制Widget、定位Widget和尺寸Widget。
Container定义
Container({
this.alignment,
this.padding, //容器内补白,属于decoration的装饰范围
Color color, // 背景色
Decoration decoration, // 背景装饰
Decoration foregroundDecoration, //前景装饰
double width,//容器的宽度
double height, //容器的高度
BoxConstraints constraints, //容器大小的限制条件
this.margin,//容器外补白,不属于decoration的装饰范围
this.transform, //变换
this.child,
})
注:①容器的大小可以通过width、height来设定,也可以通过constraints
来指定;如果它们同时存在时,width
、height
优先。
②color和decoration是相互排斥的,如果同时存在会报错!
Container的使用,示例代码如下所示:
Container(
margin: EdgeInsets.only(top: 100.0, left: 80.0), //容器外填充
width: 200.0,
height: 150.0,//容器大小
// constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0), //容器大小
decoration: BoxDecoration(//背景装饰
gradient: RadialGradient( //背景径向渐变
colors: [Colors.red, Colors.green],
center: Alignment.center,
radius:0.7
),
),
transform: Matrix4.rotationZ(0.2), //容器倾斜变换
alignment: Alignment.center, //容器内文字居中
child: Text( //卡片文字
"1314", style: TextStyle(color: Colors.white, fontSize: 40.0),
),
)
效果如下图所示:
Center(居中布局)将其子widget居中显示在自身内部的widget,继承自Align。只能有一个chlid,可以使子元素处于水平和垂直方向的中间位置。
Center定义
Center({
Key key,
double widthFactor, //宽度因子
double heightFactor, //高度因子
Widget child //
})
Center的使用,示例代码如下所示:
Center(
child: Text('Center',style: TextStyle(
color: Colors.grey,fontSize: 40.0
),),
)
效果如下图所示:
Padding即为填充组件,用于处理容器与其子元素之间的间距。与padding属性对应的是margin属性,margin是处理容器与其他组件之间的间距。
Padding定义
Padding({
Key key,
@required this.padding,//内边距
Widget child,
}) : assert(padding != null),
super(key: key, child: child);
注:padding类型为EdgeInsetsGeometry,填充值可以使用EdgeInsets方法。例如:EdgeInsets.all(6.0)将容器上下左右填充设置为6.0。
EdgeInsets
①.fromLTRB(double left,double double,double right,double bottom) :分别制定四个方向的填充
②.all(double value):所有方向都设置为同一个值
③.only({left,top,right,bottom}):设置某一方向的距离(可以同时指定多个方向)
④.symmetric({vertical,horizontal}):设置对称方向的填充:vertical指top和bottom,horizontal指left和right
Padding的使用,示例代码如下所示:
Padding(
padding: EdgeInsets.all(20),//设置全方向
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: EdgeInsets.only(top: 20),
child: Text('上面20',style: TextStyle(
color: Colors.red,fontSize: 20
),),
),
Padding(
// left, top, right, bottom
padding: EdgeInsets.fromLTRB(5,50,7,20),
child: Text('左5上50右7下20',style: TextStyle(
color: Colors.green,fontSize: 20
),),
),
Padding(
//左右各10
padding: EdgeInsets.symmetric(horizontal: 10),
child: Text('左右20',style: TextStyle(
color: Colors.blueGrey,fontSize: 20
),),
),
],
),
)
效果如下图所示:
Align组件即为对齐组件,可以将组件按指定方式对齐,也可以根据组件的大小调整自己的大小。
Align定义
Align({
Key key,
this.alignment = Alignment.center,
this.widthFactor,//宽度
this.heightFactor,//高度
Widget child,
})
各参数含义:
1.alignment:对齐方式,一般会使用系统默认提供的9种方式:
①bottomCenter(0.5,1.0) 底部中心
②bottomLeft(0.0,1.0) 左下角
③bottomRight(1.0,1.0) 右下角
④center(0.5,0.5) 水平垂直中心
⑤centerLeft(0.0,0.5) 左边缘中心
⑥centerRight(0.0,1.0) 右边缘中心
⑦topCenter(0.5,0.0)顶部中心
⑧topLeft(0.0,0.0) 左上角
⑨topRight(1.5,0.0) 右上角
Alignment实际上是包含了两个属性的,其中第一个参数,-1.0是左边对齐,1.0是右边对齐,第二个参数,-1.0是顶部对齐,1.0是底部对齐。根据这个规则,我们也可以自定义我们需要的对齐方式
2.widthFactor:宽度因子,如果设置的话,Align的宽度就是child的宽度乘以这个值,不能为负数。
3.heightFactor:高度因子,如果设置的话,Align的高度就是child的高度乘以这个值,不能为负数。
Align的使用,示例代码如下所示:
children: [
Align(
alignment: Alignment.center,
child: Text('中间'),
),
Align(
alignment: Alignment.topLeft,
child: Text('左上角'),
),
Align(
alignment: Alignment.topCenter,
child: Text('顶部中心'),
),
Align(
alignment: Alignment.topRight,
child: Text('右上角'),
),
Align(
alignment: Alignment.bottomLeft,
child: Text('左下角'),
),
Align(
alignment: Alignment.bottomCenter,
child: Text('底部中心'),
),
Align(
alignment: Alignment.bottomRight,
child: Text('右下角'),
),
Align(
alignment: Alignment.centerLeft,
child: Text('左边缘中心'),
),
Align(
alignment: Alignment.centerRight,
child: Text('右边缘中心'),
),
],
效果如下图所示:
Column(垂直布局)是一种常用的布局方式,继承自Flex,是在垂直方向排列其子组件。对Column来说,垂直方向是主轴,水平方向是次轴。
Column定义
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List children = const [],
})
各参数含义:
1.MainAxisAlignment:主轴的排列方式。
①MainAxisAlignment.start 默认值,靠上
②MainAxisAlignment.center居中
③.MainAxisAlignment.end靠下
④MainAxisAlignment.spaceAround自己填充,等待分配空间给子集,子集各自居中对齐
⑤MainAxisAlignment.spaceBetween自己填充,等待分配空间给子集,子集两侧对齐
⑥MainAxisAlignment.spaceEvenly自己填充,等待分配空间给子集,子集同一中线居中对齐
2.CrossAxisAlignment:次轴的排列方式
①CrossAxisAlignment.strech 会使子控件宽度调到最大
②CrossAxisAlignment.start 会使子控件向左对齐
③CrossAxisAlignment.center 默认值,子控件居中
④CrossAxisAlignment.end 会使子控件向右对齐
⑤CrossAxisAlignment.baseline 按文本水平线对齐,与TextBaseline搭配使用
3.MainAxisSize:主轴占据的空间。取值max为最大,min最小
①MainAxisSize.min 默认值,自适应children
②MainAxisSize.max 填充父控件竖屏,需要搭配MainAxisAlignment使用才有效果
4.VerticalDirection
①VerticalDirection.down 默认值,按照默认方式
②VerticalDirection.up CrossAxisAlignment.start和CrossAxisAlignment.end相反
5.TextBaseline
①TextBaseline.alphabetic 用于对齐字母字符底部的水平线
②TextBaseline.ideographic 用于对齐表意字符的水平线
Column的使用,示例代码如下所示:
Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.rtl,
children: [
Text('垂直布局一',style: TextStyle(
fontSize: 12
),),
Text('垂直布局二',style: TextStyle(
fontSize: 15
),),
Text('垂直布局三',style: TextStyle(
fontSize: 20
),),
],
),
效果如下图所示:
Row(水平布局)是一种常用的布局方式,使用Row组件来完成子组件在水平方向的排列。在Row组件中,水平方向是主轴,垂直方向是次轴。Row的属性和Column的属性是一样的,我们这就不细说了,直接上例子了。
Row的使用,示例代码如下所示:
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
children: [
Text('水平布局一',style: TextStyle(
fontSize: 12
),),
Text('水平布局二',style: TextStyle(
fontSize: 15
),),
Text('水平布局三',style: TextStyle(
fontSize: 20
),),
],
),
效果如下图所示:
Expanded组件可以使Row、Column、Flex等子组件在其主轴上方向展开并填充可用的空间。
注:Expanded组件必须用在Row、Column、Flex内。
Expanded的定义
Expanded({
Key key,
int flex = 1,
@required Widget child,
})
注:在Row中使用Expanded的时候,无法指定Expanded中的子组件的宽度width,但可以指定其高度height。同理,在Column中使用Expanded的时候,无法指定Expanded中的子组件的高度height,可以指定宽度width。
Expanded的使用,示例代码如下所示:
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(flex: 2, child: IconContainer(Icons.radio)),
SizedBox(width: 10),
Expanded(flex: 3, child: IconContainer(Icons.hotel)),
],
)
效果如下图所示:
FittedBox组件主要做两件事,缩放(Scale)和位置调整(Position)
FittedBox的定义
FittedBox({
Key key,
this.fit = BoxFit.contain,
this.alignment = Alignment.center,
Widget child,
})
FittedBox中有fit和alignment两个重要属性。
fit:缩放的方式,默认的属性是BoxFit.contain,child在FittedBox范围内,尽可能大,但是不会超出其尺寸。Fit的各属性:
①.BoxFit.none 没有任何填充模式
②.BoxFit.fill 不按宽高比填充模式,内容不会超出容器范围。
③.BoxFit.contain 按宽高比填充模式,内容不会超出容器范围。
④.BoxFit.cover 按原始尺寸填充整个容器模式,内容有可能会超出容器范围。
⑤.BoxFit.fitWidth及BoxFit.fitHeight分别是按宽/高填充整个容器的模式,内容不会超过容器范围。
⑥.BoxFit.scaleDown会根据情况缩小范围,有时和BoxFit.contain一样,有时和BoxFit.none一样,内容不会超过容器范围。
alignment:设置对齐方式,默认的属性是Alignment.center,居中显示child。
FittedBox的使用,示例代码如下所示:
FittedBox(
fit: BoxFit.contain,
alignment: Alignment.topCenter,
child: Text('缩放布局',style: TextStyle(
color: Colors.red,fontSize: 13.0
),),
)
效果如小图所示:
①.BoxFit.contain
②.BoxFit.fill
③.BoxFit.cover
④.BoxFit.fitWidth
⑤.BoxFit.fitHeight
⑥.BoxFit.scaleDown
Stack组件的每一个子组件要么定位,要么不定位,定位的子组件是用Positioned组件包裹的。Stack组件本身包含所有不定位的子组件,子组件根据alignment属性定位(默认为左上角)。
Stack的定义
Stack({
Key key,
this.alignment = AlignmentDirectional.topStart,
this.textDirection,
this.fit = StackFit.loose,
this.overflow = Overflow.clip,
List children = const [],
})
alignment:对齐方式,默认是左上角(topStart)。
textDirection:文本的方向,绝大部分不需要处理。
fit:用于没有定位的子组件去适应Stack的大小。StackFit.loose表示使用子组件的大小,StackFit.expand表示括伸到Stack的大小
overflow:显示超出Stack显示空间的子组件;值为Overflow.clip时,超出部分会被裁剪(隐藏),值为Overflow.visible时则不会
Positioned组件是用来定位的,根据Stack的四个角来确定子组件的位置。
Positioned的定义
Positioned({
Key key,
this.left,
this.top,
this.right,
this.bottom,
this.width,
this.height,
@required Widget child,
})
left、top、right、bottom分别代表离Stack左、上、右、下四边的距离。width和height用于指定需要定位元素的宽度和高度。
注:Positioned的width、height用于配合left、top、right、bottom来定位组件。例如,在水平方向时,你只能指定left、right、width三个属性中的两个,指定了left和width后,right会自动算出(left+width),如果同时指定三个属性的话会报错,垂直方向也是这样。
Stack、Positioned的使用,示例代码如下:
Stack(
alignment: Alignment.center, //指定未定位或部分定位widget的对齐方式
children: [
Container(
child: Icon(Icons.hotel),
),
Positioned(
left: 20.0,
child: Icon(Icons.home),
),
Positioned(
top: 20.0,
child: Icon(Icons.search,color: Colors.red,),
)
],
)
效果如下图所示:
OverflowBox组件由其minWidth、minHeight、maxWidth、maxHeight四个属性给子组件划定了一个矩形的范围。子组件不能超出OverflowBox组件范围,但是可以溢出父组件范围显示。
OverflowBox定义
OverflowBox({
Key key,
this.alignment = Alignment.center,
this.minWidth,
this.maxWidth,
this.minHeight,
this.maxHeight,
Widget child,
})
属性含义:
alignment:对齐方式。
minWidth:允许child的最小宽度。如果child宽度小于这个值,则按照最小宽度进行显示。
maxWidth:允许child的最大宽度。如果child宽度大于这个值,则按照最大宽度进行展示。
minHeight:允许child的最小高度。如果child高度小于这个值,则按照最小高度进行显示。
maxHeight:允许child的最大高度。如果child高度大于这个值,则按照最大高度进行展示。
其中,最小以及最大宽高度,如果为null的时候,就取父节点的constraint代替。
OverflowBox的使用,示例代码如下:
Container(
color: Colors.red,
width: 100.0,
height: 100.0,
padding: EdgeInsets.all(50.0),
child: OverflowBox(
alignment: Alignment.topLeft,
maxWidth: 350.0,
maxHeight: 350.0,
child: Container(
color: Colors.blue,
width: 200.0,
height: 200.0,
),
),
)
效果如下图所示:
到这里关于页面布局的讲解就结束,希望大家多多支持。