avatar

目录
从Flutter到原生开发-布局

Flutter布局

Flutter 中拥有需要将近30种内置的 布局Widget,其中常用有 Container、Padding、Center、Flex、Stack、Row、Column、ListView 等,下面简单讲解它们的特性和使用。

布局 类型 作用特点
容器 Container 只有一个子 Widget。默认充满,包含了padding、margin、color、宽高、decoration 等配置。
可滚动 GridView 使用GridView将widget放置为二维列表。 GridView提供了两个预制list,或者您可以构建自定义网格。当GridView检测到其内容太长而不适合渲染框时,它会自动滚动
居中 Center 只有一个子 Widget。只用于居中显示,常用于嵌套child,给child设置居中。
层叠 Stack 可以有多个子 Widget。 子Widget堆叠在一起。
线性 Column 可以有多个子 Widget。垂直布局。如果子widget超出屏幕范围,则会报溢出错误
线性 Row 可以有多个子 Widget。水平布局。如果子widget超出屏幕范围,则会报溢出错误
填充 Expanded 只有一个子 Widget。在 Column 和 Row 中充满。
可滚动 ListView 是一个类似列的widget,它的内容对于其渲染框太长时会自动提供滚动。
卡片 Card 接受单个子项,但该子项可以是Row,Column或其他包含子级列表的widget,显示圆角和阴影,Card内容不能滚动
弹性 Flex 如H5中的弹性盒子布局,主要通过Flex和Expanded来配合实现

Container介绍

  • Container:最常用的默认控件,但是实际上它是由多个内置控件组成的模版,只能包含一个child,支持 padding,margin,color,宽高,decoration(一般配置边框和阴影)等配置,在 Flutter 中,不是所有的控件都有 宽高、padding、margin、color 等属性,所以才会有 Padding、Center 等 Widget 的存在。
    bash
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    new Container(
    margin: EdgeInsets.all(20.0),
    height: 120.0,
    width: 500.0,
    ///透明黑色遮罩
    decoration: new BoxDecoration(
    //弧度为10.0
    borderRadius: BorderRadius.all(Radius.circular(10.0)),
    //设置了decoration的color,就不能设置Container的color。
    color: Colors.black,
    //边框
    border: new Border.all(color: Colors.blue, width: 0.3)),
    child:new Text("xixi")
    );

线性布局(Column、Row)介绍

  • Column、Row 所谓线性布局,即指沿水平或垂直方向排布子组件。它们常用的有这些属性配置:主轴方向是 start 或 center 等;副轴方向方向是 start 或 center 等;mainAxisSize 是充满最大尺寸,或者只根据子 Widget 显示最小尺寸。
    主轴和纵轴

    对于线性布局,有主轴和纵轴之分,如果布局是沿水平方向,那么主轴就是指水平方向,而纵轴即垂直方向;如果布局沿垂直方向,那么主轴就是指垂直方向,而纵轴就是水平方向。在线性布局中,有两个定义对齐方式的枚举类MainAxisAlignment和CrossAxisAlignment,分别代表主轴对齐和纵轴对齐。

    bash
    1
    2
    3
    4
    5
    6
    //主轴方向,Column的竖向、Row的横向
    mainAxisAlignment: MainAxisAlignment.start,
    //默认是最大充满、还是根据child显示最小大小
    mainAxisSize: MainAxisSize.max,
    //副轴方向,Column的横向、Row的竖向
    crossAxisAlignment :CrossAxisAlignment.center,

Row 布局

dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
new Column(
//测试Row对齐方式,排除Column默认居中对齐的干扰
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("start"),
Text("22222222")
],
),
Row(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("min"),
Text("center")
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
textDirection: TextDirection.rtl,
children: <Widget>[
Text("11111111"),
Text("rtl")
],
),

Row(
crossAxisAlignment: CrossAxisAlignment.start,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Text("11111111",style: TextStyle(fontSize: 30.0),),
Text("start")
],
)
],
)

解释:

  • 第一个Row很简单,默认为居中对齐;第二个Row,由于mainAxisSize值为MainAxisSize.min,Row的宽度等于两个Text的宽度和,所以对齐是无意义的,所以会从左往右显示;第三个Row设置textDirection值为TextDirection.rtl,所以子组件会从右向左的顺序排列,而此时MainAxisAlignment.end表示左对齐,所以最终显示结果就是图中第三行的样子;第四个Row测试的是纵轴的对齐方式,由于两个子Text字体不一样,所以其高度也不同,我们指定了verticalDirection值为VerticalDirection.up,即从低向顶排列,而此时crossAxisAlignment值为CrossAxisAlignment.start表示底对齐。

Column 布局

Column可以在垂直方向排列其子组件。参数和Row一样,不同的是布局方向为垂直,主轴纵轴正好相反,读者可类比Row来理解,下面看一个例子:
dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import 'package:flutter/material.dart';

class CenterColumnRoute extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text("hi"),
Text("world"),
],
);
}
}

解释

  1. 由于我们没有指定Column的mainAxisSize,所以使用默认值MainAxisSize.max,则Column会在垂直方向占用尽可能多的空间,此例中为屏幕高度。
  2. 由于我们指定了 crossAxisAlignment 属性为CrossAxisAlignment.center,那么子项在Column纵轴方向(此时为水平方向)会居中对齐。注意,在水平方向对齐是有边界的,总宽度为Column占用空间的实际宽度,而实际的宽度取决于子项中宽度最大的Widget。在本例中,Column有两个子Widget,而显示“world”的Text宽度最大,所以Column的实际宽度则为Text(“world”) 的宽度,所以居中对齐后Text(“hi”)会显示在Text(“world”)的中间部分。

实际上,Row和Column都只会在主轴方向占用尽可能大的空间,而纵轴的长度则取决于他们最大子元素的长度。

特殊情况

如果Row里面嵌套Row,或者Column里面再嵌套Column,那么只有对最外面的Row或Column会占用尽可能大的空间,里面Row或Column所占用的空间为实际大小,下面以Column为例说明:

dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Container(
color: Colors.green,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.max, //有效,外层Colum高度为整个屏幕
children: <Widget>[
Container(
color: Colors.red,
child: Column(
mainAxisSize: MainAxisSize.max,//无效,内层Colum高度为实际高度
children: <Widget>[
Text("hello world "),
Text("I am Jack "),
],
),
)
],
),
),
);

如果要让里面的Column占满外部Column,可以使用Expanded 组件

dart
1
2
3
4
5
6
7
8
9
10
11
12
Expanded( 
child: Container(
color: Colors.red,
child: Column(
mainAxisAlignment: MainAxisAlignment.center, //垂直方向居中对齐
children: <Widget>[
Text("hello world "),
Text("I am Jack "),
],
),
),
)

弹性布局(Flex)

Expanded 介绍

  • Expanded 在 Column 和 Row 中代表着平均充满的作用,当有两个存在的时候默认均分充满。同时页可以设置 flex 属性决定比例。
    bash
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    new Column(
    ///主轴居中,即是竖直向居中
    mainAxisAlignment: MainAxisAlignment.center,
    ///大小按照最小显示
    mainAxisSize : MainAxisSize.min,
    ///横向也居中
    crossAxisAlignment : CrossAxisAlignment.center,
    children: <Widget>[
    ///flex默认为1
    new Expanded(child: new Text("1111"), flex: 2,),
    new Expanded(child: new Text("2222")),
    ],
    );
打赏
  • 微信
    微信
  • 支付寶
    支付寶

评论