Flutter實戰之基本佈局篇

JulyYu發表於2019-08-07

佈局

The core of Flutter’s layout mechanism is widgets. In Flutter, almost everything is a widget—even layout models are widgets.

1、Column & Row & Flex

將Column、Row、Flex放在一小節是因為不同之處只是對子Widget佈局方式不同。Column垂直佈局子元件,Row是水平佈局子元件,Flex根據direction設定Axis.horizontal或是Axis.vertical。

Flutter實戰之基本佈局篇 Flutter實戰之基本佈局篇
Column(
  children: <Widget>[
    Text("text"),
    Text("text"),
    Text("text"),
  ],
);
Row(
  children: <Widget>[
    Text("text"),
    Text("text"),
    Text("text"),
  ],
);
Flex(
  direction: Axis.vertical,
  children: <Widget>[
    Text("text"),
    Text("text"),
    Text("text"),
  ],
);
Flex(
  direction: Axis.horizontal,
  children: <Widget>[
    Text("text"),
    Text("text"),
    Text("text"),
  ],
);
複製程式碼

另外元件都不支援滑動,一旦子元件較多超出可顯示範圍,在Debug模式下會出現warning提示錯誤。通常情況下一般是使用ListView而非Column去顯示列表,當然可以在Column、Row、Flex外層巢狀SingleChildScrollView使其支援滑動。

Flutter實戰之基本佈局篇

Tips

  • Column和Row不支援對Padding,margin以及寬高的設定,一般外層巢狀Container或是Padding元件實現約束佈局寬度和間距。
  • Expanded元件也是在Column和Row中經常使用,通過它對子元件進行權重大小劃分。類似於Android的XML佈局檔案中weight屬性,Expanded中有flex引數用於設定比重比例,數值越大比重越大。
  • MainAxisAlignment屬性是與當前元件方向一致的軸,例如Row的主軸是水平方向,當設定MainAxisAlignment對於Row來說是在水平方向。支援的設定引數有:start、end、center、spaceBetween、spaceAround、spaceEvenly。詳見文件
  • CrossAxisAlignment屬性是與當前元件方向成垂直的軸,例如Row的交叉軸就是垂直方向,當設定MainAxisAlignment對於Row來說是在垂直方向。支援的設定引數有:start、end、center、stretch、baseline詳見文件
  • MainAxisSize屬性可設定:max、min,預設為max。類似於Android中math_content和wrap_content,當為min時大小根據子元件約束大小如果為max時大小根據自身約束大小。
  • Column和Row繼承自Flex。個人理解在一些特定UI佈局中可以使用Flex,例如需要切換垂直和水平佈局的時候選用。

2、Expanded & Flexible

這節是彈性佈局,上節已經有提到Column和Row使用子元件時通過巢狀彈性佈局Expanded重來分配佈局空間,同時也說過Flutter中彈性佈局類似於Android中XML的weight屬性。可知Expanded元件繼承自Flexible,唯獨不同的是Flexible的fit屬性值預設FlexFit.loose並且可設定,Expanded的fit屬性值是FlexFit.tight並且不能設定。

Flexible

class Flexible extends ParentDataWidget<Flex> {
  /// Creates a widget that controls how a child of a [Row], [Column], or [Flex]
  /// flexes.
  const Flexible({
    Key key,
    this.flex = 1,
    this.fit = FlexFit.loose,
    @required Widget child,
  }) : super(key: key, child: child);
複製程式碼

Expanded

const Expanded({
  Key key,
  int flex = 1,
  @required Widget child,
}) : super(key: key, flex: flex, fit: FlexFit.tight, child: child);
複製程式碼

FlexFit屬性:tight、loose。tight會讓子元件強制填充可用最大布局空間;loose會讓子元件儘可能填充可用佈局空間。字面上的意思tight比loose更強烈,如下例項設定tight比起loose會佔用更多佈局空間,而loose會根據巢狀的元件而定是否根據比重填充更多空間。

Column(
        children: <Widget>[
          Flexible(
            flex: 2,
            child: Container(
              color: Colors.blue,
              child: Center(
                child: Text(
                  "Flexible 2",
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ),
          Flexible(
            flex: 1,
            fit: FlexFit.tight,
            child: Container(
              child: Text(
                "Flexible 1 FlexFit.tight",
              ),
            ),
          ),
          Flexible(
            flex: 1,
            fit: FlexFit.tight,
            child: Container(
              child: Text(
                "Flexible 1 FlexFit.tight",
              ),
            ),
          ),
          Center(
            child: Text(
              "NO Flexible",
            ),
          ),
        ],
      );
複製程式碼
Flutter實戰之基本佈局篇 Flutter實戰之基本佈局篇

Tips

  • 例如Flexible內部巢狀了Center元件即便FlexFit是loose元件填充空間還是會按照比重獲取對應比例的大小。而沒有內部沒有巢狀Center元件的Flexible則沒有按照比重填充空間而是根據自身元件實際大小填充。詳見文件
  • Spacer是一個空元件,主要用於填充空白區域,預設flex為1。
  • Flexible可以解決在Column和Row設定子元件Text的文字超出範圍警告問題。原先以為使用Text屬性overflow: TextOverflow.ellipsis可以解決但實際情況不可行。其實只需要在Text外層巢狀Flexible並能解決。

相關文章