RowWidget

  • Flutter中的row控件就是水平控件,它可以让Row里边的子元素进行水平排列
  • Row控件可以分为灵活排列和非灵活排列两种,这两种模式都需要熟练掌握,等经验丰富后可根据需求进行使用

非灵活排列

  • 从字面上就可以理解到,不灵活就是根据Row子元素的大小,进行布局。如果子元素不足,它会留有空隙,如果子元素超出,它会警告
  • 比如现在我们要制作三个按钮,并让三个按钮同时在一排
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
39
40
41
42
43
44
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context){
return MaterialApp(
title: 'Row Widget',
home: Scaffold(
appBar: new AppBar(
title: new Text('水平方向布局'),
),
body: new Row(
// children 复数 child单数
children: <Widget>[
new RaisedButton(
onPressed: (){

},
color:Colors.redAccent,
child: new Text('红色按钮'),
),
new RaisedButton(
onPressed:(){

},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
),
new RaisedButton(
onPressed:(){

},
color:Colors.pinkAccent,
child: new Text('粉色按钮'),
),
]
)
)
);
}
}

  • 这时候你会发现的页面已经有了三个按钮,但这三个按钮并没有充满一行,而是出现了空隙。这就是不灵活横向排列造成的。它根据子元素的大小来进行排列。如果我们想实现充满一行的效果,就要使用灵活水平布局了

灵活排列

  • 解决上面有空隙的问题,可以使用Expanded来进行解决,也就是我们说的灵活布局。我们在按钮的外边加入Expanded就可以了
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
39
40
41
42
import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',

home:Scaffold(
appBar:new AppBar(
title:new Text('水平方向布局'),
),
body:new Row(
children: <Widget>[
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.redAccent,
child:new Text('红色按钮')
)),
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
)

),
Expanded(child:new RaisedButton(
onPressed: (){
},
color:Colors.pinkAccent,
child:new Text('粉色按钮')
)
)
],
)
),
);
}
}

  • 如果这时候想让中间的按钮大,而两边的按钮保持真实大小,就可以不灵活和灵活模式进行混用,只让中间按钮实现灵活排列,自然会挤占空白区域
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
39
40
41
42
43
import 'package:flutter/material.dart';
void main () => runApp(MyApp());

class MyApp extends StatelessWidget{
@override
Widget build(BuildContext context ){
return MaterialApp(
title:'ListView widget',

home:Scaffold(
appBar:new AppBar(
title:new Text('水平方向布局'),
),
body:new Row(
children: <Widget>[
new RaisedButton(
onPressed: (){

},
color:Colors.redAccent,
child:new Text('红色按钮')
),
Expanded(child:new RaisedButton(
onPressed: (){

},
color:Colors.orangeAccent,
child: new Text('黄色按钮'),
)

),
new RaisedButton(
onPressed: (){
},
color:Colors.pinkAccent,
child:new Text('粉色按钮')
)
],
)
),
);
}
}

ColumnWidget

  • Column组件即垂直布局控件,能够将子组件垂直排列

对齐方式

  • column里加入三行文字,然后看一下效果
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
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ColumnWidget',
home: Scaffold(
appBar: new AppBar(
title: new Text('垂直布局'),
),
body:Column(
// crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text('Hello',style: TextStyle(fontSize: 20.0)),
Text('Hello Wrold',style: TextStyle(fontSize: 20.0)),
Text('Hello',style: TextStyle(fontSize: 20.0)),
],)
),
);
}
}

  • 这时候你会发现文字是以最长的一段文字居中对齐的,看起来很别扭。那如果想让文字以左边开始对齐,只需要加入一个对齐属性
    • CrossAxisAlignment.star:居左对齐
    • CrossAxisAlignment.end:居右对齐
    • CrossAxisAlignment.center:居中对齐
1
crossAxisAlignment: CrossAxisAlignment.start,

主轴/副轴

  • 在设置对齐方式mainAxisAlignment属性,意思就是主轴对齐方

    • main轴:如果你用column组件,那垂直就是主轴,如果你用Row组件,那水平就是主轴
    • cross轴:cross轴我们称为幅轴,是和主轴垂直的方向。比如Row组件,那垂直就是幅轴,Column组件的幅轴就是水平方向的
  • 比如现在我们要把上面的代码,改成垂直方向居中。因为用的是Column组件,所以就是主轴方向,这时候你要用的就是主轴对齐了

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
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ColumnWidget',
home: Scaffold(
appBar: new AppBar(
title: new Text('垂直布局'),
),
body:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text('Hello',style: TextStyle(fontSize: 20.0)),
Text('Hello World',style: TextStyle(fontSize: 20.0)),
Text('Hello',style: TextStyle(fontSize: 20.0)),
],)
),
);
}
}
  • 让文字相对于水平方向居中,只要加入Center组件就可以轻松解决
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
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ColumnWidget',
home: Scaffold(
appBar: new AppBar(
title: new Text('垂直布局'),
),
body:Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Center(child: Text('Hello',style: TextStyle(fontSize: 20.0))),
Center(child: Text('Hello World',style: TextStyle(fontSize: 20.0))),
Center(child: Text('Hello',style: TextStyle(fontSize: 20.0))),
],)
),
);
}
}

Expanded

  • 比如我们想让中间区域变大,而头部区域和底部根据文字所占空间进行显示。使用灵活和非灵活的混合用法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ColumnWidget',
home: Scaffold(
appBar: new AppBar(
title: new Text('垂直布局'),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(child: Text('I am Xiaoli')),
Expanded(child: Center(child: Text('my website is xiaoliblog.cn'))),
Center(child: Text('I love coding'))
],
)),
);
}
}

StackWidget

  • 水平布局和垂直布局确实很好用,但是有一种情况是无法完成的,比如放入一个图片,图片上再写一些字或者放入容器,这时候Row和Column就力不从心了。Flutter为这种情况准备了Stack层叠布局

Alignment

  • alignment属性是控制层叠的位置的,建议在两个内容进行层叠时使用。它有两个值X轴距离和Y轴距离,值是从0到1的,都是从上层容器的左上角开始算起的
  • CircleAvatar这个经常用来作头像的,组件里边有个radius的值可以设置图片的弧度
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
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context){
var stack = new Stack(
alignment: const FractionalOffset(0.5, 0.8),
children:<Widget>[
new CircleAvatar(
backgroundImage: new NetworkImage('https://cdn.jsdelivr.net/gh/xiaoliblog/MyCDNRepo/img/headerimg.png'),
radius: 100.0,
),
new Container(
decoration: new BoxDecoration(
color: Colors.lightBlue,
),
padding:EdgeInsets.all(5.0),
child: new Text('Xiao Li Blog')
)
]
);

return MaterialApp(
title: 'StackWidget',
home:Scaffold(
appBar: new AppBar(
title: new Text('重叠布局'),
),
body:Center(child: stack,)
)
);
}
}

Positioned

  • Positioned组件用于超过两个组件的层叠进行定位,Positioned组件的属性
1
2
3
4
5
6
bottom ---距离层叠组件下边的距离
left ---距离层叠组件左边的距离
top ---距离层叠组件上边的距离
right ---距离层叠组件右边的距离
width ---层叠定位组件的宽度
height ---层叠定位组件的高度
  • 修改上述例子,文字不在放入到container组件里,而是直接放入到Positioned里,并且不再是两个组件,而是三个子组件
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
39
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context){
var stack = new Stack(
alignment: const FractionalOffset(0.5, 0.8),
children:<Widget>[
new CircleAvatar(
backgroundImage: new NetworkImage('https://cdn.jsdelivr.net/gh/xiaoliblog/MyCDNRepo/img/headerimg.png'),
radius: 100.0,
),
new Positioned(
top: 10.0,
left: 10.0,
child: new Text('Xiaoliblog.cn',style: TextStyle(color:Colors.red),)
),
new Positioned(
bottom: 10.0,
right: 10.0,
child: new Text('小李博客',style: TextStyle(color:Colors.red),)
)
]
);

return MaterialApp(
title: 'StackWidget',
home:Scaffold(
appBar: new AppBar(
title: new Text('层叠布局'),
),
body:Center(child: stack)
)
);
}
}

Align

  • Align 是一个 具有 Alignment 属性的 Widget,基础的属性就是 alignment,并且默认值是 Aligment.center;用于实现相对定位
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

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// 去掉右上角debug
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text('Flutter')),
body: HomePage()
)
);
}
}

class HomePage extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Container(
width:200,
height:200,
color: Colors.green,
child: Align(
alignment: Alignment.bottomCenter,
child: FlutterLogo(
size: 60,
),
),
);
}
}

CardWidget

  • Flutter还有一种比较比较酷炫的布局方式,我称 它为卡片式布局。这种布局类似ViewList,但是列表会以物理卡片的形态进行展示
  • 比如我们现在要开发一个类似收获地址的列表,并且列表外部使用一个卡片式布局
  • 卡片式布局默认是撑满整个外部容器的,如果你想设置卡片的宽高,需要在外部容器就进行制定
  • 代码中使用了一个垂直布局组件Column组件,然后利用了ListTile实现内部列表,这里需要说明的是ListTile不光可以使用在ListView组件中,然后容器组件其实都可以使用
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
39
40
41
42
43
44
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget{

@override
Widget build(BuildContext context){
var card = new Card(
child: Column(
children: <Widget>[
ListTile(
title:new Text('湖南省长沙市雨花区',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('小李博客'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
ListTile(
title:new Text('湖南省长沙市雨花区',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('小李博客'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
ListTile(
title:new Text('湖南省长沙市雨花区',style: TextStyle(fontWeight: FontWeight.w500),),
subtitle: new Text('小李博客'),
leading: new Icon(Icons.account_box,color: Colors.lightBlue,),
),
new Divider(),
]
)
);

return MaterialApp(
title: 'StackWidget',
home:Scaffold(
appBar: new AppBar(
title: new Text('卡片布局'),
),
body:Center(child: card)
)
);
}
}