7. Flutter - 基础组件 之 布局Widget
1. Align组件
const Align({
Key key,
// 对齐方式
this.alignment = Alignment.center,
// 宽度因子,不设置的情况,会尽可能大
this.widthFactor,
// 高度因子,不设置的情况,会尽可能大
this.heightFactor,
// 要布局的子Widget
Widget child,
})
Alignment对齐方式设置
文档中已经为我们定义了一些常量:如下
static const Alignment topLeft = Alignment(-1.0, -1.0);
/// The center point along the top edge.
static const Alignment topCenter = Alignment(0.0, -1.0);
/// The top right corner.
static const Alignment topRight = Alignment(1.0, -1.0);
/// The center point along the left edge.
static const Alignment centerLeft = Alignment(-1.0, 0.0);
/// The center point, both horizontally and vertically.
static const Alignment center = Alignment(0.0, 0.0);
/// The center point along the right edge.
static const Alignment centerRight = Alignment(1.0, 0.0);
/// The bottom left corner.
static const Alignment bottomLeft = Alignment(-1.0, 1.0);
/// The center point along the bottom edge.
static const Alignment bottomCenter = Alignment(0.0, 1.0);
/// The bottom right corner.
static const Alignment bottomRight = Alignment(1.0, 1.0);
center
为 Alignment(0.0, 0.0)
,topLeft
为 Alignment(-1.0, -1.0)
,这些值均是以父视图为准进行的设置。父视图范围内取值为(-1.0, -1.0) ~ (1.0, 1.0)
,中心点为(0.0, 0.0)
。当然我们也可以取值(0, 2)
,(3,0)
等,这不过会超出父视图显示范围。
widthFactor和heightFactor作用
- 子组件在父组件中的对齐方式必须有一个前提,就是父组件得知道自己的范围(宽度和高度);
- 如果widthFactor和heightFactor不设置,那么默认Align会尽可能的大(尽可能占据自己所在的父组件);
- 我们也可以对他们进行设置,比如widthFactor设置为5,那么相对于Align的宽度是子组件跨度的5倍;
-
代码演示:
ps:
Container为容器视图,主要为了设置背景色及大小,方便观察,后面会有介绍。
class AlignTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: [
Container(
margin: EdgeInsets.all(20),
color: Colors.blue,
child: Align(
child: Icon(Icons.pets, size: 36, color: Colors.red),
//左上
alignment: Alignment(-1, -1),
widthFactor: 5,
heightFactor: 5,
),
),
Container(
padding: EdgeInsets.all(10),
color: Colors.green,
child: Align(
child: Icon(Icons.pets, size: 36, color: Colors.red),
//右下角
alignment: Alignment(1, 1),
widthFactor: 3,
heightFactor: 3,
),
)
],
);
}
}
-
显示效果:
Align效果演示.png
2. Center 组件
class Center extends Align {
const Center({
Key key,
double widthFactor,
double heightFactor,
Widget child
}) : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
Center
组件继承自Align
,只是将alignment
设置为Alignment.center
,且Align
的 alignment
属性默认为 Alignment.center
,
所以其实Align(alignment = Alignment.center
)可以与 Center
相互替换,效果是一样的。
3. Padding组件
Padding在其他端也是一个属性而已,但是在Flutter中是一个Widget,但是Flutter中没有Margin这样一个Widget,这是因为外边距也可以通过Padding来完成。
Padding通常用于设置子Widget到父Widget的边距(你可以称之为是父组件的内边距或子Widget的外边距)。
-
代码演示:
class PaddingTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
width: 300,
height: 300,
color: Colors.green,
child: Padding(
padding: EdgeInsets.all(20),
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
border: Border.all(color: Colors.red, width: 3)),
child: Text('测试')),
),
);
}
}
如下图,Padding的设置对于绿色视图,相当于内边距;而对于蓝色视图则是外边距。
显示效果4. Container 组件
Container组件类似于iOS中的UIView,主要负责视图的承载,可以通过它设置背景色、边框、圆角等等。
Container({
Key key,
//AlignmentGeometry类型可选命名参数,容器内子Widget如何对其,使用其子类Alignment
this.alignment,
//EdgeInsetsGeometry类型可选命名参数,设置容器内边距
this.padding,
//Color类型可选命名参数,容器填充色
Color color,
//Decoration类型可选命名参数,绘制在child子Widget后面的装饰,使用BoxDecoration
Decoration decoration,
//Decoration类型可选命名参数,绘制在child子Widget前面的装饰,使用BoxDecoration
this.foregroundDecoration,
//double类型可选命名参数,容器的宽度
double width,
//double类型可选命名参数,容器的高度
double height,
//BoxConstraints类型可选命名参数,对child设置的Widget的约束
BoxConstraints constraints,
//EdgeInsetsGeometry类型可选命名参数,设置容器外边距
this.margin,
//Matrix4类型可选命名参数,在绘制容器之前要应用的转换矩阵
this.transform,
//Widget类型可选命名参数,容器包含的子Widget
this.child,
})
容器的大小可以通过width、height属性来指定,也可以通过constraints来指定,如果同时存在时,width、height优先。实际上Container内部会根据width、height来生成一个constraints;
color
和decoration
是互斥的,不可同时设置。
-
BoxDecoration
Container有一个非常重要的属性 decoration,他对应的类型是Decoration类型,但是它是一个抽象类。
在实际开发中,我们经常使用它的实现类BoxDecoration来进行实例化。
const BoxDecoration({
//Color类型可选命名参数,填充背景色
this.color,
//DecorationImage类型可选命名参数,在背景或渐变上绘制的图像
this.image,
//BoxBorder类型可选命名参数,边框设置
this.border,
//BorderRadiusGeometry类型可选命名参数,设置圆角
this.borderRadius,
//List<BoxShadow>类型可选命名参数,盒子后面的盒子投射的阴影列表
this.boxShadow,
//Gradient类型可选命名参数,填充框时使用的渐变
this.gradient,
//BlendMode类型可选命名参数,应用于框的颜色或渐变背景的混合模式
this.backgroundBlendMode,
//BoxShape类型可选命名参数,将背景颜色、渐变和图像填充到并作为boxShadow投射的形状
this.shape = BoxShape.rectangle,
})
示例代码:
class ContainerTest extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
// width: 400,
// height: 400,
padding: EdgeInsets.all(20),
color: Colors.lightBlue,
child: Container(
width: 280,
height: 280,
//内边距
// padding: EdgeInsets.all(100),
//外边距
// margin: EdgeInsets.all(80),
// 不可与 decoration 同时设置
// color: Colors.red,
//变形:旋转
transform: Matrix4.rotationZ(0.1),
//装饰:设置颜色。渐变色、形状、阴影等。
decoration: BoxDecoration(
color: Colors.green,
//渐变
gradient: LinearGradient(
colors: [Colors.blue, Colors.red, Colors.green]),
//形状
shape: BoxShape.circle,
//阴影
boxShadow: [
BoxShadow(offset: Offset(10, 10), color: Colors.grey)
],
backgroundBlendMode: BlendMode.srcOver,
border: Border.all(color: Colors.orange, width: 5)),
child: Icon(
Icons.people,
color: Colors.orange,
size: 100,
)),
);
}
}
显示效果.png
5. Flex组件
Row
组件和Column
组件都继承自Flex组件。
Flex组件和Row、Column属性主要的区别就是多一个direction。
当direction
的值为Axis.horizonta
l的时候,则是Row
。
当direction
的值为Axis.vertical
的时候,则是Column
。
-
5.1 Row组件
Row({
Key key,
//主轴对齐方式
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
//主轴大小(水平方向尽可能大)
MainAxisSize mainAxisSize = MainAxisSize.max,
// 交叉处对齐方式
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
// 水平方向子widget布局顺序
TextDirection textDirection,
//表示Row纵轴(垂直)的对齐方向
VerticalDirection verticalDirection = VerticalDirection.down,
// 如果上面是baseline对齐方式
TextBaseline textBaseline = TextBaseline.alphabetic,
// 子widget列表
List<Widget> children = const <Widget>[],
})
mainAxisSize:
表示Row在主轴(水平)方向占用的空间,默认是MainAxisSize.max
,Row的宽度始终等于水平方向的最大宽度
而MainAxisSize.min
表示尽可能少的占用水平空间,Row的实际宽度等于所有子widgets占用的的水平空间;mainAxisAlignment:
表示子Widgets在Row所占用的水平空间内对齐方式
如果mainAxisSize值为MainAxisSize.min
,则此属性无意义
,因为子widgets的宽度等于Row的宽度
只有当mainAxisSize的值为MainAxisSize.max时,此属性才有意义
MainAxisAlignment.start表示沿textDirection的初始方向对齐,
如textDirection取值为TextDirection.ltr时,则MainAxisAlignment.start表示左对齐,textDirection取值为TextDirection.rtl时表示从右对齐。
而MainAxisAlignment.end和MainAxisAlignment.start正好相反;
MainAxisAlignment.center表示居中对齐。crossAxisAlignment:
表示子Widgets在纵轴方向的对齐方式
Row的高度等于子Widgets中最高的子元素高度
它的取值和MainAxisAlignment一样(包含start、end、 center三个值)
不同的是crossAxisAlignment的参考系是verticalDirection,即verticalDirection值为VerticalDirection.down时crossAxisAlignment.start指顶部对齐,verticalDirection值为VerticalDirection.up时,crossAxisAlignment.start指底部对齐;而crossAxisAlignment.end和crossAxisAlignment.start正好相反;
5.2 Column组件
Column组件与 Row组件使用方式完全一致,只是方向不同而已。
Column({
Key key,
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
MainAxisSize mainAxisSize = MainAxisSize.max,
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
TextDirection textDirection,
VerticalDirection verticalDirection = VerticalDirection.down,
TextBaseline textBaseline,
List<Widget> children = const <Widget>[],
})