Flutter佈局Widget--彈性佈局、線性佈局、流式佈局和層疊佈局

前言 本文咱們要介紹 Flutter 中佈局 Widget,包括彈性佈局、線性佈局 流式佈局和層疊佈局。 1、彈性佈局--Flex Flex 相似 Android 中的 FlexboxLayout,和 Expanded 配合使用能夠實現子Widget 按照必定比例來分配父容器空間。微信

使用:app

Flex( direction: Axis.horizontal, children: [ ... ], )less

其中direction:主軸的方向,是必選參數,它的類型是 Axis,有如下兩種值: (1)Axis.horizontal:主軸方向爲水平方向,那麼子Widget 就會沿水平方向排列,交叉方向是垂直方向。 (2)Axis.vertical:主軸方向爲垂直方向,那麼子Widget 就會沿垂直方向排列,交叉方向是水平方向。ide

Flex 的構造函數及參數說明函數

class Flex extends MultiChildRenderObjectWidget { Flex({ Key key, @required this.direction,//必選;類型 Axis;主軸的方向 this.mainAxisAlignment = MainAxisAlignment.start,//可選;類型 MainAxisAlignment;表示子Widget在主軸的對齊方式 this.mainAxisSize = MainAxisSize.max,//可選;類型 MainAxisSize;表示主軸應該佔用多大的空間,分爲mix 和 max this.crossAxisAlignment = CrossAxisAlignment.center,//可選;類型 CrossAxisAlignment;表示子Widget在交叉軸的對齊方式 this.textDirection,//可選;類型 TextDirection;表示子Widget在主軸方向上的佈局順序,分爲rtl:從右到左 和 ltr:從左到右 this.verticalDirection = VerticalDirection.down,//可選;類型 VerticalDirection;表示子Widget在交叉軸方向上的佈局順序 this.textBaseline,//可選;類型 TextBaseline;排列子Widget 時使用哪一個基線 List children = const [],//可選;類型 List< Widget>;Flex佈局 裏排列的內容 }) : assert(direction != null), assert(mainAxisAlignment != null), assert(mainAxisSize != null), assert(crossAxisAlignment != null), assert(verticalDirection != null), assert(crossAxisAlignment != CrossAxisAlignment.baseline || textBaseline != null), super(key: key, children: children); ... }佈局

Flexible 與 Expanded 爲了不子Widget 在 Row、Column、Flex中超屆,就可使用 Flexible 和 Expanded,當子Widget 要超過主軸的大小時,會自動換行。其中 Expanded 是 Flexible 的子類。學習

Flexible( child: Text('內容'), ) //或 Expanded( child: Text('內容'), )flex

(1)Flexible 的構造函數及參數說明: class Flexible extends ParentDataWidget { const Flexible({ Key key, this.flex = 1, //可選;類型 int;此 Widget的彈性因子 this.fit = FlexFit.loose,//可選;類型 FlexFit;如何分配彈性Widget在可用空間裏的大小 @required Widget child,//必選;類型 Widget;要顯示的Widget }) : super(key: key, child: child); ... }ui

(2)Expanded 的構造函數及參數說明: class Expanded extends Flexible { /// Creates a widget that expands a child of a [Row], [Column], or [Flex] /// expand to fill the available space in the main axis. const Expanded({ Key key, int flex = 1, @required Widget child, }) : super(key: key, flex: flex, fit: FlexFit.tight, child: child); }this

(3)Flexible 與 Expanded 的區別: fit 參數不一樣,Expanded 用的是默認的,當還有剩餘空間的時候,會佔滿剩餘的所有空間。而 Flexible 用的是 FlexFit.loose,只佔用自身大小的空間。 (4)flex 彈性係數: 當 flex 爲0或null,則 child 是沒有彈性的,稱爲非彈性子Widget,非彈性子Widget的大小就是其自己的大小,不會被擴展去佔用多餘的空間 。 當 flex 大於0時,child 是有彈性的,稱爲彈性子Widget,首先會計算出第一步全部 flex 爲0或null的子Widget 的大小,而後會按照彈性子Widget的flex佔全部彈性子Widget的flex總和的比例分割主軸的空閒空間。 2、線性佈局 Flutter 的線性佈局和 Android 中的同樣分爲水平方向的線性佈局Row和垂直方向的線性佈局Column。

  1. Row

使用:

Row( children: [ Text("Hello Flutter"), Image.asset( "images/flutter.png", width: 200, ) ], )

Row 的構造函數及參數說明:

class Row extends Flex { Row({ Key key, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,//可選;類型 MainAxisAlignment;表示子Widget 在主軸的對齊方式 MainAxisSize mainAxisSize = MainAxisSize.max,//可選;類型 MainAxisSize;表示主軸應該佔用多大的空間 CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,//可選;類型 CrossAxisAlignment;表示子Widget在交叉軸的對齊方式 TextDirection textDirection,//可選;類型TextDirection;表示子Widget在主軸方向上的佈局參數 VerticalDirection verticalDirection = VerticalDirection.down,//可選;類型VerticalDirection;表示子Widget在交叉軸方向上的佈局順序 TextBaseline textBaseline,//可選;類型TextBaseline;排列子Widget時使用哪一個基線 List children = const [],//可選;類型List< Widget>;Flex佈局裏排列的內容 }) : super( children: children, key: key, direction: Axis.horizontal, mainAxisAlignment: mainAxisAlignment, mainAxisSize: mainAxisSize, crossAxisAlignment: crossAxisAlignment, textDirection: textDirection, verticalDirection: verticalDirection, textBaseline: textBaseline, ); }

  1. Column

使用:

Column( children: [ Text("Hello Flutter"), Image.asset( "images/flutter.png", width: 200, ) ], )

Column 的構造函數及參數說明: 和 Row 的參數同樣

注意:若是 Row 嵌套 Row,或者 Column 嵌套 Column,那麼只有最外面的 Row 或 Column 會佔用盡量大的空間,裏面 Row 或 Column 所佔用的空間爲實際的大小。

3、流式佈局--Wrap 頁面元素的寬度能夠按照屏幕分辨率進行適配調整,把超出屏幕顯示範圍的控件自動換行。

使用:

Wrap( direction: Axis.horizontal, children: [ ... ] )

代碼示例:

import 'package:flutter/material.dart';

class WrapWidget extends StatelessWidget { @override Widget build(BuildContext context) { return new MaterialApp( title: 'WrapWidget', home: new Scaffold( appBar: new AppBar( title: new Text('WrapWidget'), ), body: Wrap( direction: Axis.horizontal, spacing: 10.0, runSpacing: 5.0, children: [ new Chip( avatar: new CircleAvatar( backgroundColor: Colors.blue, child: new Text('1'), ), label: new Text('AAAAAAAAAA')), new Chip( avatar: new CircleAvatar( backgroundColor: Colors.blue, child: new Text('1'), ), label: new Text('BBBBB')), new Chip( avatar: new CircleAvatar( backgroundColor: Colors.blue, child: new Text('1'), ), label: new Text('CCCCCCCCCCC')), new Chip( avatar: new CircleAvatar( backgroundColor: Colors.blue, child: new Text('2'), ), label: new Text('DDDDDDDD')), new Chip( avatar: new CircleAvatar( backgroundColor: Colors.blue, child: new Text('2'), ), label: new Text('EEEEEE')), ], ), ), ); } }

運行結果:

Wrap 的構造函數及參數說明:

class Wrap extends MultiChildRenderObjectWidget { Wrap({ Key key, this.direction = Axis.horizontal,//可選;類型 Axis;主軸的方向,默認是 Axis.horizontal this.alignment = WrapAlignment.start,//可選;類型 WrapAlignment;子Widget在主軸上的對齊方式,默認值爲WrapAlignment.start,和MainAxisAlignment的同樣 this.spacing = 0.0,//可選;類型 double;主軸的方向間距 this.runAlignment = WrapAlignment.start,//可選;類型 WrapAlignment;Wrap 會自動換成或換列,runAlignment 就是每行或每列的對齊方式,若是主軸爲水平方向,就是每行,若是主軸爲豎直方向,就是每列,默認值爲WrapAlignment.start,WrapAlignment 的值和 MainAxisAlignment 的同樣 this.runSpacing = 0.0,//可選;類型 double;每行或每列之間的間距,默認是0.0 this.crossAxisAlignment = WrapCrossAlignment.start,//可選;類型 WrapCrossAlignment;子Widget 在交叉軸上的對齊方式,WrapCrossAligment.start,WrapCrossAligment的值和MainAxisAligment的同樣 this.textDirection,//可選;類型 TextDirection;表示子Widget在主軸方向上的佈局順序 this.verticalDirection = VerticalDirection.down,//可選;類型 VerticalDirection;表示子Widget在交叉軸方向上的佈局順序 List children = const [],//可選;類型 List;Wrap佈局裏排序的內容 }) : super(key: key, children: children); ... }

4、層疊佈局--Stack Flutter 中的層疊佈局相似 Android 中的 FrameLayout,其子Widget 會按照添加順序肯定顯示層級,後面添加的會覆蓋在前面添加的 Widget 上面。

使用:

Stack( children: [ Image.asset( "images/flutter.png", width: 200, fit: BoxFit.cover, ), Text('Hello Flutter',style: TextStyle(fontSize: 50.0),), ], )

Stack 的構造函數及參數說明:

class Stack extends MultiChildRenderObjectWidget { Stack({ Key key,//可選;類型 Key;Widget的標識 this.alignment = AlignmentDirectional.topStart,//可選;類型AlignmentDirectional this.fit = StackFit.loose,//可選;類型 StackFit;此參數用於決定 non-positioned 子Widget 如何去適應Stack的大小 this.overflow = Overflow.clip,//可選;類型 Overflow;決定如何顯示超出 Stack顯示空間的子Widget List children = const [],//可選;類型 List;Stack佈局裏排序的內容 }) : super(key: key, children: children); ... }

(1)alignment 參數: 決定如何對齊 non-positioned 子Widget 和部分 position 子Widget,默認值爲Alignment.topStart,部分 positioned 子Widget,在某一個軸上沒有定義的,這個軸就使用 alignment 的值,好比left、right爲橫軸,left 和right 都沒有定義,就是橫軸沒有定義,只要這兩個一個有值,這個軸就算有值;top、bottom爲縱軸,同理。 AlignmentDirectional 的值: AlignmentDirectional.topStart:上邊 start 對齊 AlignmentDirectional.topCenter:上邊 居中 對齊 AlignmentDirectional.topEnd:上邊 end 對齊 AlignmentDirectional.centerStart:中間 start 對齊 AlignmentDirectional.center:中間對齊 AlignmentDirectional.centerEnd:中間 end 對齊 AlignmentDirectional.bottomStart:下邊 start 對齊 AlignmentDirectional.bottomCenter:下邊 居中 對齊 AlignmentDirectional.bottomEnd:下邊 end 對齊 (2)fit 參數: 用於決定 non-positioned 子Widget 如何去適應Stack的大小。 StackFit 的值: StackFit.loose:使用子Widget 自身的大小 StackFit.expand:子Widget 擴伸到 Stack 的大小 StackFit.passthrough:Stack 的父Widget 的約束無修改的傳遞給 Stack 的子Widget (3)overflow 參數: 決定如何顯示超出 Stack顯示空間的子Widget。 overflow 的值: Overflow.visible:超出部分仍能看見 Overflow.clip:超出部分會被剪裁

Stack 的子Widget 爲了肯定子Widget 到父容器四個角的位置,Stack將子Widget 分爲兩類:positioned 子Widget 和 non-positioned 子Widget。 (1)Positioned positioned 子Widget 是指被 Positioned 嵌套起來的 Widget,Positioned 能夠控制子Widget 到父容器四個邊的距離。

使用: Stack( fit: StackFit.expand, children: [ Positioned( left: 50, top: 100, child: Image.asset( "images/flutter.png", width: 200, fit: BoxFit.cover, ), ), Text('Hello Flutter'), ], ),

Positioned 的構造函數及參數說明: class Positioned extends ParentDataWidget { const Positioned({ Key key,//可選;類型 Key;Widget的標識 this.left,//可選;類型 double;離Stack左邊的距離 this.top,//可選;類型 double;離Stack上邊的距離 this.right,//可選;類型 double;離Stack右邊的距離 this.bottom,//可選;類型 double;離Stack底邊的距離 this.width,//可選;類型 double;指定Widget的寬度 this.height,//可選;類型 double;指定Widget的高度 @required Widget child, }) : assert(left == null || right == null || width == null), assert(top == null || bottom == null || height == null), super(key: key, child: child); ... }

注意:此處的width、height 是用於配合 left、top、right、bottom 來定位 Widget 的。而且在水平方向上,只能指定 left、right、width 三個屬性中的兩個,若是三個都指定就會報錯;垂直方向同理。

(2)non-positioned子Widget non-positioned 子Widget 就是不用 Positioned 嵌套起來的 Widget,non-positioned 子Widget 使用 Stack 設置的 alignment 來肯定本身在父容器裏的位置。

小編這呢,給你們推薦一個優秀的iOS交流平臺,平臺裏的夥伴們都是很是優秀的iOS開發人員,咱們專一於技術的分享與技巧的交流,你們能夠在平臺上討論技術,交流學習。歡迎你們的加入(想要進入的可加小編微信)。

微信號:17336563535

來源:本文爲第三方轉載,若有侵權請聯繫小編刪除。

相關文章
相關標籤/搜索