最常見的布局模式之一是垂直或水平排列widget。您可以使用行(Row)水平排列widget,并使用列(Column)垂直排列widget。
重點是什么?
要在Flutter中創(chuàng)建行或列,可以將一個widget列表添加到Row 或Column 中。 同時,每個孩子本身可以是一個Row或一個Column,依此類推。以下示例顯示如何在行或列內(nèi)嵌套行或列。
此布局按行組織。該行包含兩個孩子:左側(cè)的一列和右側(cè)的圖片:
左側(cè)的Column widget樹嵌套行和列。
您將在嵌套行和列中實現(xiàn)一些Pavlova(圖片中的奶油水果蛋白餅)的布局代碼
注意:行和列是水平和垂直布局的基本、低級widget - 這些低級widget允許最大化的自定義。Flutter還提供專門的,更高級別的widget,可能足以滿足您的需求。 例如,您可能更喜歡ListTile而不是Row,ListTile是一個易于使用的小部件,具有前后圖標(biāo)屬性以及最多3行文本。您可能更喜歡ListView而不是列,ListView是一種列狀布局,如果其內(nèi)容太長而無法適應(yīng)可用空間,則會自動滾動。 有關(guān)更多信息,請參閱通用布局widget。
您可以控制行或列如何使用mainAxisAlignment和crossAxisAlignment屬性來對齊其子項。 對于行(Row)來說,主軸是水平方向,橫軸垂直方向。對于列(Column)來說,主軸垂直方向,橫軸水平方向。
MainAxisAlignment 和CrossAxisAlignment 類提供了很多控制對齊的常量.
注意: 將圖片添加到項目時,需要更新pubspec文件才能訪問它們 - 此示例使用Image.asset
顯示圖像。 有關(guān)更多信息,請參閱此示例的pubspec.yaml文件, 或在Flutter中添加資源和圖像。如果您使用的是網(wǎng)上的圖片,則不需要執(zhí)行此操作,使用Image.network
即可。
在以下示例中,3個圖像中的每一個都是100像素寬。渲染盒(在這種情況下,整個屏幕)寬度超過300個像素, 因此設(shè)置主軸對齊方式為spaceEvenly,它會在每個圖像之間,之前和之后均勻分配空閑的水平空間。
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Image.asset('images/pic1.jpg'),
Dart code: main.dartImages: imagesPubspec: pubspec.yaml
列的工作方式與行相同。以下示例顯示了一列,包含3個圖片,每個圖片高100個像素。 渲染盒(在這種情況下,整個屏幕)的高度大于300像素,因此設(shè)置主軸對齊方式為spaceEvenly,它會在每個圖像之間,上方和下方均勻分配空閑的垂直空間。
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Image.asset('images/pic1.jpg'),
Dart code: main.dartImages: imagesPubspec: pubspec.yaml
*注意: 如果布局太大而不適合設(shè)備,則會在受影響的邊緣出現(xiàn)紅色條紋。例如,以下截圖中的行對于設(shè)備的屏幕來說太寬:
通過使用Expanded widget,可以將widget的大小設(shè)置為適和行或列,這在下面的調(diào)整 widgets 部分進(jìn)行了描述。
也許你想要一個widget占據(jù)其兄弟widget兩倍的空間。您可以將行或列的子項放置在Expandedwidget中, 以控制沿著主軸方向的widget大小。Expanded widget具有一個flex屬性,它是一個整數(shù),用于確定widget的彈性系數(shù),默認(rèn)彈性系數(shù)是1。
例如,要創(chuàng)建一個由三個widget組成的行,其中中間widget的寬度是其他兩個widget的兩倍,將中間widget的彈性系數(shù)設(shè)置為2:
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Image.asset('images/pic1.jpg'),
),
new Expanded(
flex: 2,
child: new Image.asset('images/pic2.jpg'),
),
new Expanded(
Dart code: main.dartImages: imagesPubspec: pubspec.yaml
要修復(fù)上一節(jié)中的示例:其中一行有3張圖片,行對于其渲染框太寬,并且導(dǎo)致右邊出現(xiàn)紅色條中的問題,可以使用Expanded widget來包裝每個widget。 默認(rèn)情況下,每個widget的彈性系數(shù)為1,將行的三分之一分配給每個小部件。
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
new Expanded(
child: new Image.asset('images/pic1.jpg'),
),
new Expanded(
child: new Image.asset('images/pic2.jpg'),
),
new Expanded(
默認(rèn)情況下,行或列沿著其主軸會盡可能占用盡可能多的空間,但如果要將孩子緊密聚集在一起,可以將mainAxisSize設(shè)置為MainAxisSize.min。 以下示例使用此屬性將星形圖標(biāo)聚集在一起(如果不聚集,五張星形圖標(biāo)會分散開)。
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
var packedRow = new Row(
mainAxisSize: MainAxisSize.min,
children: [
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.green[500]),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
],
);
// ...
}
布局框架允許您根據(jù)需要在行和列內(nèi)部再嵌套行和列。讓我們看下面紅色邊框圈起來部分的布局代碼:
紅色邊框部分的布局通過兩個行來實現(xiàn)。評級行包含五顆星和評論數(shù)量。圖標(biāo)行包含三列圖標(biāo)和文本。
評級行的widget樹:
該ratings變量創(chuàng)建一個包含5個星形圖標(biāo)和一個文本的行:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
var ratings = new Container(
padding: new EdgeInsets.all(20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Row(
mainAxisSize: MainAxisSize.min,
children: [
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
new Icon(Icons.star, color: Colors.black),
],
),
new Text(
'170 Reviews',
style: new TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 20.0,
),
),
],
),
);
//...
}
}
提示: 為了最大限度地減少由嵌套嚴(yán)重的布局代碼導(dǎo)致的視覺混淆,可以在變量和函數(shù)中實現(xiàn)UI的各個部分。
評級行下方的圖標(biāo)行包含3列; 每個列都包含一個圖標(biāo)和兩行文本,您可以在其widget樹中看到:
該iconList變量定義了圖標(biāo)行:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
// ...
var descTextStyle = new TextStyle(
color: Colors.black,
fontWeight: FontWeight.w800,
fontFamily: 'Roboto',
letterSpacing: 0.5,
fontSize: 18.0,
height: 2.0,
);
// DefaultTextStyle.merge可以允許您創(chuàng)建一個默認(rèn)的文本樣式,該樣式會被其
// 所有的子節(jié)點繼承
var iconList = DefaultTextStyle.merge(
style: descTextStyle,
child: new Container(
padding: new EdgeInsets.all(20.0),
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
new Column(
children: [
new Icon(Icons.kitchen, color: Colors.green[500]),
new Text('PREP:'),
new Text('25 min'),
],
),
new Column(
children: [
new Icon(Icons.timer, color: Colors.green[500]),
new Text('COOK:'),
new Text('1 hr'),
],
),
new Column(
children: [
new Icon(Icons.restaurant, color: Colors.green[500]),
new Text('FEEDS:'),
new Text('4-6'),
],
),
],
),
),
);
// ...
}
}
該leftColumn變量包含評分和圖標(biāo)行,以及描述Pavlova的標(biāo)題和文字:
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
//...
var leftColumn = new Container(
padding: new EdgeInsets.fromLTRB(20.0, 30.0, 20.0, 20.0),
child: new Column(
children: [
titleText,
subTitle,
ratings,
iconList,
],
),
);
//...
}
}
左列放置在容器中以約束其寬度。最后,用整個行(包含左列和圖像)放置在一個Card內(nèi)構(gòu)建UI:
Pavlova圖片來自 Pixabay ,可以在Creative Commons許可下使用。 您可以使用Image.network直接從網(wǎng)上下載顯示圖片,但對于此示例,圖像保存到項目中的圖像目錄中,添加到pubspec文件, 并使用Images.asset。 有關(guān)更多信息,請參閱在Flutter中添加Asserts和圖片。
body: new Center(
child: new Container(
margin: new EdgeInsets.fromLTRB(0.0, 40.0, 0.0, 30.0),
height: 600.0,
child: new Card(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
new Container(
width: 440.0,
child: leftColumn,
),
mainImage,
],
),
),
),
),
Dart code: main.dartImages: imagesPubspec: pubspec.yaml
提示: Pavlova示例在廣泛的橫屏設(shè)備(如平板電腦)上運行最佳。如果您在iOS模擬器中運行此示例, 則可以使用Hardware > Device菜單選擇其他設(shè)備。對于這個例子,我們推薦iPad Pro。 您可以使用Hardware > Rotate將其方向更改為橫向模式 。您還可以使用Window > Scale更改模擬器窗口的大?。ú桓倪壿嬒袼氐臄?shù)量)
更多建議: