flutter--Stack & Positioned & Align 层叠布局与定位

Stackflutter–模拟登录中出现过,这里来详细了解一下这个Widget,类似于css中的position: relative,但是会强制子Widget层叠显示,Positioned类似于css中的position: absolute,可以设置坐标。

Stack

1
2
3
4
5
6
7
8
Stack({
Key key,
AlignmentGeometry alignment: AlignmentDirectional.topStart,
TextDirection textDirection,
StackFit fit: StackFit.loose,
Overflow overflow: Overflow.clip,
List<Widget> children: const[]
})

先看一个只有children的demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Stack(
children: <Widget>[
Text('1'),
Text('2'),
Text('3')
],
)
)
);
}
}


1、2、3叠在了一起,哪一个在上哪一个在下,把Text换成Container再看一下,

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

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Stack(
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red
),
Container(
width: 50,
height: 50,
color: Colors.green
)
],
)
)
);
}
}


可以看见和css里一样,后写的在上。

alignment

Widget的对齐方式
AlignmentDirectional.topStart (默认值)、AlignmentDirectional.topCenterAlignmentDirectional.topEndAlignmentDirectional.centerStartAlignmentDirectional.centerAlignmentDirectional.centerEndAlignmentDirectional.bottomStartAlignmentDirectional.bottomCenterAlignmentDirectional.bottomEnd
简单易懂,看个demo。

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

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Stack(
alignment: AlignmentDirectional.bottomCenter,
children: <Widget>[
Container(
width: 100,
height: 100,
color: Colors.red
),
Container(
width: 50,
height: 50,
color: Colors.green
),
Container(
width: 30,
height: 30,
color: Colors.blue
)
],
)
)
);
}
}

textDirection

Widget的排列方式,默认值是TextDirection.ltr,从左往右,当设置为TextDirection.rtl时效果如下:

fit

Widget中未定位元素的大小,只有两个值:
StackFit.loose:不对其大小进行约束(默认值)
StackFit.expand:最大
StackFit.passthrough:父级的约束直接传递给子Widgert

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

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
width: 200,
height: 200,
child: Stack(
fit: StackFit.passthrough,
children: <Widget>[
Container(
width: 50,
height: 50,
color: Colors.red
)
],
)
)
)
);
}
}


这里需要注意的是fit值如果不是默认值StackFit.loose,子Widget设置的尺寸将失去作用。

overflow

css里效果一样,只有两个值
Overflow.clip:溢出将被剪切
Overflow.visible:不对溢出的部分做处理

Positioned

定位元素,用于Stack的子Widget

1
2
3
4
5
6
7
8
9
10
Positioned({
Key key,
double left,
double top,
double right,
double bottom,
double width,
double height,
@required Widget child
})

都是基础属性,lefttoprightbottom是相对于父级的坐标。

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

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Stack(
children: <Widget>[
Positioned(
width: 100,
height: 100,
left: 100,
bottom: 100,
child: Container(
color: Colors.red
)
)
],
)
)
);
}
}


相对于左下角的距离是100、100.

Align

这个更简单一点,只是设定子Widget相对于Align的位置。

1
2
3
4
5
6
7
Align({
Key key,
AlignmentGeometry alignment: Alignment.center,
double widthFactor,
double heightFactor,
Widget child
})

alignment

Widget相对于Align的位置。

widthFactor & heightFactor

这两个相当于是系数,乘以子Widget的宽高,就是Align的尺寸。

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 {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment.bottomRight,
child: Container(
width: 50,
height: 50,
color: Colors.blue
)
)
)
);
}
}


这里需要注意一点,就是如果Align的父级设有宽高widthFactorheightFactor将市区作用,大小为最大。

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

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

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
home: Scaffold(
body: Container(
width: 300,
height: 300,
color: Colors.red,
child: Align(
widthFactor: 2,
heightFactor: 2,
alignment: Alignment.bottomRight,
child: Container(
width: 50,
height: 50,
color: Colors.blue
)
)
)
)
);
}
}

  • © 2020-02 MonkeyInWind
  • GitHub

请我喝杯咖啡吧~