做自(zì)由與創造的先行者

Flutter 布局多個widgets

Flutter開(kāi)發手冊

垂直和(hé)水(shuǐ)平放(fàng)置多個widget

最常見的布局模式之一是垂直或水(shuǐ)平排列widget。您可以使用(yòng)行(Row)水(shuǐ)平排列widget,并使用(yòng)列(Column)垂直排列widget。

重點是什(shén)麽?

行和(hé)列是兩種最常用(yòng)的布局模式。

行和(hé)列都需要一個子widget列表。

子widget本身可以是行、列或其他(tā)複雜(zá)widget。

您可以指定行或列如何在垂直或水(shuǐ)平方向上(shàng)對(duì)齊其子項

您可以拉伸或限制特定的子widget.

您可以指定子widget如何使用(yòng)行或列的可用(yòng)空(kōng)間.

要在Flutter中創建行或列,可以将一個widget列表添加到(dào)Row 或Column 中。 同時(shí),每個孩子本身可以是一個Row或一個Column,依此類推。以下(xià)示例顯示如何在行或列内嵌套行或列。

注意:行和(hé)列是水(shuǐ)平和(hé)垂直布局的基本、低(dī)級widget - 這(zhè)些(xiē)低(dī)級widget允許最大(dà)化的自(zì)定義。Flutter還提供專門(mén)的,更高(gāo)級别的widget,可能(néng)足以滿足您的需求。 例如,您可能(néng)更喜歡ListTile而不是Row,ListTile是一個易于使用(yòng)的小(xiǎo)部件,具有前後圖标屬性以及最多3行文(wén)本。您可能(néng)更喜歡ListView而不是列,ListView是一種列狀布局,如果其内容太長而無法适應可用(yòng)空(kōng)間,則會(huì)自(zì)動滾動。 有關更多信息,請(qǐng)參閱通用(yòng)布局widget。

對(duì)齊 widgets

您可以控制行或列如何使用(yòng)mainAxisAlignment和(hé)crossAxisAlignment屬性來(lái)對(duì)齊其子項。 對(duì)于行(Row)來(lái)說,主軸是水(shuǐ)平方向,橫軸垂直方向。對(duì)于列(Column)來(lái)說,主軸垂直方向,橫軸水(shuǐ)平方向。

MainAxisAlignment 和(hé)CrossAxisAlignment 類提供了(le)很(hěn)多控制對(duì)齊的常量.

注意: 将圖片添加到(dào)項目時(shí),需要更新pubspec文(wén)件才能(néng)訪問它們 - 此示例使用(yòng)Image.asset顯示圖像。 有關更多信息,請(qǐng)參閱此示例的pubspec.yaml文(wén)件, 或在Flutter中添加資源和(hé)圖像。如果您使用(yòng)的是網上(shàng)的圖片,則不需要執行此操作(zuò),使用(yòng)Image.network即可。

在以下(xià)示例中,3個圖像中的每一個都是100像素寬。渲染盒(在這(zhè)種情況下(xià),整個屏幕)寬度超過300個像素, 因此設置主軸對(duì)齊方式爲spaceEvenly,它會(huì)在每個圖像之間,之前和(hé)之後均勻分配空(kōng)閑的水(shuǐ)平空(kōng)間。

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

列的工(gōng)作(zuò)方式與行相同。以下(xià)示例顯示了(le)一列,包含3個圖片,每個圖片高(gāo)100個像素。 渲染盒(在這(zhè)種情況下(xià),整個屏幕)的高(gāo)度大(dà)于300像素,因此設置主軸對(duì)齊方式爲spaceEvenly,它會(huì)在每個圖像之間,上(shàng)方和(hé)下(xià)方均勻分配空(kōng)閑的垂直空(kōng)間。

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

調整 widget

也(yě)許你(nǐ)想要一個widget占據其兄弟widget兩倍的空(kōng)間。您可以将行或列的子項放(fàng)置在Expandedwidget中, 以控制沿着主軸方向的widget大(dà)小(xiǎo)。Expanded widget具有一個flex屬性,它是一個整數,用(yòng)于确定widget的彈性系數,默認彈性系數是1。

例如,要創建一個由三個widget組成的行,其中中間widget的寬度是其他(tā)兩個widget的兩倍,将中間widget的彈性系數設置爲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(

a row of 3 images with the middle image twice as wide as the others

Dart code: main.dartImages: imagesPubspec: pubspec.yaml

要修複上(shàng)一節中的示例:其中一行有3張圖片,行對(duì)于其渲染框太寬,并且導緻右邊出現(xiàn)紅(hóng)色條中的問題,可以使用(yòng)Expanded widget來(lái)包裝每個widget。 默認情況下(xià),每個widget的彈性系數爲1,将行的三分之一分配給每個小(xiǎo)部件。

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(

聚集 widgets

默認情況下(xià),行或列沿着其主軸會(huì)盡可能(néng)占用(yòng)盡可能(néng)多的空(kōng)間,但(dàn)如果要将孩子緊密聚集在一起,可以将mainAxisSize設置爲MainAxisSize.min。 以下(xià)示例使用(yòng)此屬性将星形圖标聚集在一起(如果不聚集,五張星形圖标會(huì)分散開(kāi))。

class _MyHomePageState extends State {

@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),

],

);

// ...

}

嵌套行和(hé)列

布局框架允許您根據需要在行和(hé)列内部再嵌套行和(hé)列。

該ratings變量創建一個包含5個星形圖标和(hé)一個文(wén)本的行:

class _MyHomePageState extends State {

@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,

),

),

],

),

);

//...

}

}

提示: 爲了(le)最大(dà)限度地減少由嵌套嚴重的布局代碼導緻的視(shì)覺混淆,可以在變量和(hé)函數中實現(xiàn)UI的各個部分。

該iconList變量定義了(le)圖标行:

class _MyHomePageState extends State {

@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可以允許您創建一個默認的文(wén)本樣式,該樣式會(huì)被其

// 所有的子節點繼承

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變量包含評分和(hé)圖标行,以及描述Pavlova的标題和(hé)文(wén)字:

class _MyHomePageState extends State {

@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,

],

),

);

//...

}

}

左列放(fàng)置在容器中以約束其寬度。最後,用(yòng)整個行(包含左列和(hé)圖像)放(fàng)置在一個Card内構建UI:

Pavlova圖片來(lái)自(zì) Pixabay ,可以在Creative Commons許可下(xià)使用(yòng)。 您可以使用(yòng)Image.network直接從(cóng)網上(shàng)下(xià)載顯示圖片,但(dàn)對(duì)于此示例,圖像保存到(dào)項目中的圖像目錄中,添加到(dào)pubspec文(wén)件, 并使用(yòng)Images.asset。 有關更多信息,請(qǐng)參閱在Flutter中添加Asserts和(hé)圖片。

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示例在廣泛的橫屏設備(如平闆電腦(nǎo))上(shàng)運行最佳。如果您在iOS模拟器中運行此示例, 則可以使用(yòng)Hardware > Device菜單選擇其他(tā)設備。對(duì)于這(zhè)個例子,我們推薦iPad Pro。 您可以使用(yòng)Hardware > Rotate将其方向更改爲橫向模式 。您還可以使用(yòng)Window > Scale更改模拟器窗口的大(dà)小(xiǎo)(不更改邏輯像素的數量)

網站(zhàn)建設開(kāi)發|APP設計(jì)開(kāi)發|小(xiǎo)程序建設開(kāi)發
下(xià)一篇:Flutter 常用(yòng)布局widgets
上(shàng)一篇:Flutter 布局方法