開篇
Row和Column分別是Flutter中的水平和垂直佈局,它們都是MultiChildRenderObjectWidget,所以它們都是可以渲染多個孩子的控件,而它們是如何渲染孩子的大小和位置的則是有renderObject定義的。它們的繼承關係圖如下:
MainAxisAlignment和CrossAxisAlignment
Row、Column的佈局特性和MainAxisAlignment(主軸)和CrossAxisAlignment(交叉軸)有關。主軸是與當前控件方向一致的軸,而交叉軸就是與當前控件方向垂直方向的軸。主軸和交叉軸是相對於的,它們主要用於控制Row,Column的子控件排列位置。因此,在Row中,MainAxisAlignment的方向是水平的,默認的起始位置在左邊,排列方向是從左至右;而CrossAxisAlignment的方向則是垂直的,默認的起始位置在中間,排列方向是從上到下。
相對的,在Column中,MainAxisAlignment的方向是垂直的,默認起始位置在上邊,排列方向是從上至下;CrossAxisAlignment的方向則是水平的,默認的起始位置在中間,排列方向是從左到右。另外,textDirection和verticalDirection可以分別改變水平和垂直方向的起始位置和排列方向。
MainAxisAlignment的值:
enum MainAxisAlignment {
//將子控件放在主軸的開始位置
start,
//將子控件放在主軸的結束位置
end,
//將子控件放在主軸的中間位置
center,
//將主軸空白位置進行均分,排列子元素,手尾沒有空隙
spaceBetween,
//將主軸空白區域均分,使中間各個子控件間距相等,首尾子控件間距爲中間子控件間距的一半
spaceAround,
//將主軸空白區域均分,使各個子控件間距相等
spaceEvenly,
}
CrossAxisAlignment取值:
enum CrossAxisAlignment {
//將子控件放在交叉軸的起始位置
start,
//將子控件放在交叉軸的結束位置
end,
//將子控件放在交叉軸的中間位置
center,
//使子控件填滿交叉軸
stretch,
//將子控件放在交叉軸的上,並且與基線相匹配(不常用)
baseline,
}
textDirection取值:
enum TextDirection {
//從右到左排列
rtl,
//從左到右排列
ltr,
}
VerticalDirection取值
enum VerticalDirection {
//從上到下
up,
//從下到上
down,
}
定義控件Box
爲了實例說明的方便,這裏專門封裝一個box控件來說明Row和Column佈局特性。
class Box extends StatelessWidget {
String index;
double boxSize = 100.0;
Box(String index) {
this.index = index;
}
@override
Widget build(BuildContext context) {
return Container(
width: boxSize,
height: boxSize,
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.orangeAccent, Colors.orange, Colors.deepOrange]
)
),
child: Text(
index,
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold
),
),
);
}
}
Row
(1)Row的默認情況
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
可以看出來,Row的默認起始位置在左邊,排列方向是從左到右。也就是:
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(2)使用textDirection和verticalDirection將默認值取全反
爲了看出verticalDirection: VerticalDirection.up的效果,故意把crossAxisAlignment設置爲了CrossAxisAlignment.start
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.rtl,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(3)使用verticalDirection只改變垂直方向的默認位置和排列方向
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(4)使用textDirection只改變水平方向的默認位置和排列方向
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.rtl,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(5)居中
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.rtl,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(6)填滿交叉軸
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 200.0,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
Column
(1)Column的默認情況
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
也就是Column的默認情況是:
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(2)使用textDirection和verticalDirection將默認值改爲全反
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.rtl,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(3)使用verticalDirection只改變垂直方向的默認位置和排列方向
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(4)使用textDirection只改變水平方向的默認位置和排列方向
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
textDirection: TextDirection.rtl,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(5)居中
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.up,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}
(6)填滿交叉軸
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Container(
color: Colors.green,
height: 600.0,
width: 400.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.stretch,
textDirection: TextDirection.ltr,
verticalDirection: VerticalDirection.down,
children: <Widget>[
Box("1"),
Box("2"),
Box("3"),
Box("4")
],
),
),
);
}
}