Flutter開發中,佈局比較另類一點,由於邏輯代碼和佈局代碼都寫在一塊兒了,都是使用Dart來寫。數組
Flutter中的佈局容器主要分爲兩類:只能包含一個子Widget的佈局容器和能夠包含多個子Widget的容器bash
Center組件中的子組件會居中顯示。Center組件會盡量的大,若是你不給它設置任何約束。下面是Center組件的使用方法:app
import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Center( child: new Text("hello world") ), ), ); } }
Container是使用很是多的一個佈局容器,關於Container容器的顯示規則,有以下幾條:less
下面的代碼展現了Container的用法:ide
import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Container( width: 100.0, height: 100.0, color: Colors.red, child: new Text("Flutter!"), ) ), ); } }
Container還能夠設置內邊距和外邊距,以下代碼所示:佈局
body: new Container(
// 設置外邊距都爲20.0
margin: const EdgeInsets.all(20.0),
// 設置內邊距,4個邊分別設置
padding: const EdgeInsets.fromLTRB(10.0, 20.0, 30.0, 40.0),
width: 100.0,
height: 100.0,
color: Colors.red,
child: new Text("Flutter!"), )
Padding組件專門用於給它的子組件設置內邊距,用法比較簡單:ui
new Padding(
padding: new EdgeInsets.all(8.0),
child: const Card(child: const Text('Hello World!')), )
Align組件用於將它的子組件放置到肯定的位置,好比下面的代碼展現了將Text組件放置到100*100的容器的右下角:spa
new Container(
width: 100.0,
height: 100.0,
color: Colors.red,
child: new Align(
child: new Text("hello"), alignment: Alignment.bottomRight, ), )
FittedBox
組件根據fit
屬性來肯定子組件的位置,fit
屬性是一個BoxFit
類型的值,BoxFit
是個枚舉類,取值有以下幾種:code
enum BoxFit {
fill,
contain,
cover,
fitWidth,
fitHeight,
none,
scaleDown,
}
在大小爲200*100的Container中放置一個Text,使用FittedBox來控制Text的不一樣顯示狀態:orm
new Container(
width: 200.0,
height: 100.0,
color: Colors.red,
child: new FittedBox(
child: new Text("hello world"), fit: BoxFit.fill, ) )
AspectRatio組件
AspectRatio組件用於讓它的子組件按必定的比例顯示,下面是示例代碼:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new AspectRatio( // Container組件按16:9(width / height)顯示 aspectRatio: 16.0 / 9.0, child: new Container( color: Colors.red, ), ) ), ); } }
若是將aspectRatio設置爲1.0,則Container顯示爲正方形。(注意,Dart中/
表明除法運算,不是取整運算,使用~/
作取整運算)
ConstrainedBox組件用於給它的子組件強制加上一些約束,好比下面的代碼:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new ConstrainedBox( constraints: const BoxConstraints.expand(width: 50.0, height: 50.0), child: new Container( color: Colors.red, width: 200.0, height: 200.0, ) ) ), ); } }
這兩個組件的做用是將他們的子組件調整到組件自己的寬度/高度。
這個類是很是有用的,例如,當寬度/高度沒有任何限制時,你會但願子組件按更合理的寬度/高度顯示而不是無限的擴展。
LimitedBox是一個當其自身不受約束時才限制其大小的容器。
若是這個組件的最大寬度是沒有約束,那麼它的寬度就限制在maxWidth
。相似地,若是這個組件的最大高度沒有約束,那麼它的高度就限制在maxHeight
。
Offstage組件用於顯示或隱藏它的子組件,以下代碼所示:
new Offstage(
offstage: false, // true: 隱藏, false: 顯示 child: new Text("hello world"), )
OverflowBox組件它給它的子組件帶來不一樣的約束,而不是從它的父組件中獲得,可能容許子組件溢出到父組件中。
SizedOverflowBox組件是一個指定大小的組件,它的約束會傳遞給子組件,子組件可能溢出。
SizedBox是一個指定了大小的容器。
若是指定了SizedBox的大小,則子組件會使用SizedBox的大小,若是沒有指定SizedBox的大小,則SizedBox會使用子組件的大小。若是SizedBox沒有子組件,SizedBox會按它本身的大小來顯示,將nulls看成0。
new SizedBox(
// 若是指定width和height,則Container按照指定的大小顯示,而不是Container本身的大小,若是沒有指定width和height,則SizedBox按照Container的大小顯示
width: 50.0,
height: 50.0,
child: new Container(
color: Colors.red,
width: 300.0,
height: 300.0,
),
)
Transform用於在繪製子組件前對子組件進行某些變換操做,好比平移、旋轉、縮放等。
示例代碼以下:
new Container(
color: Colors.black,
child: new Transform(
alignment: Alignment.topRight,
// 須要導包:import 'dart:math' as math; transform: new Matrix4.skewY(0.3)..rotateZ(-math.pi / 12.0), child: new Container( padding: const EdgeInsets.all(8.0), color: const Color(0xFFE8581C), child: const Text('Apartment for rent!'), ), ), )
Row組件字面理解就是表明一行,在一行中能夠放入多個子組件。
下面是示例代碼:
import 'package:flutter/material.dart'; main() { runApp(new MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ new Text("hello"), new Container( width: 50.0, height: 50.0, color: Colors.red, ), new Text("world") ], ) ), ); } }
Row組件的構造方法中,children
參數是一個數組,表示能夠有多個子組件,mainAxisAlignment
表示Row中的子組件在主軸(Row組件主軸表示水平方向,交叉軸表示垂直方向,Column組件主軸表示垂直方向,交叉軸表示水平方向)上的對齊方式,能夠有以下幾個取值:
Column組件
Column組件表示一列,能夠在一列中放入多個組件,以下代碼所示:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Column( children: <Widget>[ new Text("hello"), new Text("world"), new Text("nihao~") ], ) ), ); } }
Column和Row組件同樣,能夠經過MainAxisAlignment
或者CrossAxisAlignment
來設置主軸和交叉軸的對齊方式,這裏再也不贅述。
Stack組件相似於Android中的FrameLayout,其中的子組件是一層層堆起來的,並不像Row或者Column中的子組件,按水平或垂直方向排列,下面用代碼說明:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Stack( children: <Widget>[ new Container( width: 100.0, height: 100.0, color: Colors.red, ), new Container( width: 30.0, height: 30.0, color: Colors.green, ) ], ) ), ); } }
IndexedStack用於根據索引來顯示子組件,index爲0則顯示第一個子組件,index爲1則顯示第二個子組件,以此類推,下面用代碼說明:
new IndexedStack(
index: 1,
children: <Widget>[
new Container(
width: 100.0,
height: 100.0,
color: Colors.red,
child: new Center(
child: new Text("index: 0", style: new TextStyle(fontSize: 20.0),), ), ), new Container( width: 100.0, height: 100.0, color: Colors.green, child: new Center( child: new Text("index: 1", style: new TextStyle(fontSize: 20.0),), ), ) ], )
IndexedStack的構造方法中有個index
屬性,上面的index
屬性爲1,則顯示的是children
數組中的第2個元素(綠色方塊),
若是index
改成0,則顯示的是第1個元素(紅色方塊),若是index
的大小超過了children數組的長度,則會報錯。
Table組件用於顯示多行多列的佈局,若是隻有一行或者一列,使用Row或者Column更高效。下面用一段代碼展現Table的用法:
class MyApp extends StatelessWidget {
// 生成Table中的數據
List<TableRow> getData() { var data = [ "hello", "world" ]; List<TableRow> result = new List<TableRow>(); TextStyle style = new TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold); for (int i = 0; i < data.length; i++) { String str = data[i]; List<Widget> row = new List(); for (int j = 0; j < str.length; j++) { row.add(new Text(" ${str[j]} ", style: style)); } result.add(new TableRow( children: row )); } return result; } @override Widget build(BuildContext context) { return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Table( children: getData() ) ), ); } }
Wrap組件能夠在水平或垂直方向上多行顯示其子組件,下面是示例代碼:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp( title: "Test", home: new Scaffold( appBar: new AppBar( title: new Text("Test") ), body: new Wrap( spacing: 5.0, // 水平方向上兩個子組件的間距 runSpacing: 20.0, // 兩行的垂直間距 children: <Widget>[ new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), new Text("hello"), ], ) ), ); } }
若是你把上面代碼中的Wrap換成Row,你會發現Row中的子組件超過屏幕寬度後,不會自動換行顯示。
ListView是一個很是經常使用的組件。