今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

Flutter佈局基礎——Row水平佈局

Flutter 佈局基礎 ——Row 水平佈局#

Flutter 中水平佈局使用Row,可設定元素水平方向排列,如果想要子元素充滿,可把子元素使用Expanded包括起來。

背景#

使用Row佈局的 Widget,不能滑動;通常使用 Row 佈局的時候,默認所有的子元素加起來不能超過父視圖的寬度。如果想要橫向滑動,可考慮使用 ListView。

Ps:當所有子元素的寬度超出了父視圖Row的寬度後,會有警告。

如果想要豎向佈局,使用Column

如果只有一個元素,可考慮使用Align或者Center來佈局。

基礎介紹#

  • Row 常用屬性
    • children: 子視圖
    • textDirection: 子視圖佈局方向
      • TextDirection.ltr: 從左到右
      • TextDirection.rtl: 從右到左
    • mainAxisAlignment: 子視圖在父視圖上的佈局方式,水平方向佈局
      • MainAxisAlignment.spaceAround: 子視圖之間和子視圖距離父視圖都留有間距
      • MainAxisAlignment.center: 所有子試圖居中
      • MainAxisAlignment.end: 所有子視圖居最末尾
      • MainAxisAlignment.spaceBetween: 子視圖之間留有相等間距,與父視圖不留間距
      • MainAxisAlignment.spaceEvenly: 子視圖之間和子視圖距離父視圖都留有間距,且間距都相等
      • MainAxisAlignment.start,所有子視圖居於最開始

注意 mainAxisAlignment 在子元素使用了Expanded時,沒有效果;當所有子元素超出了父視圖的寬度時,也沒有效果。

子元素不使用Expanded,那麼子元素的寬度是根據內容適應,即內容有多少,寬度就有多少。示例如下:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: Row(
          children: [
            Text(
              'First',
              style: TextStyle(backgroundColor: Colors.lightBlueAccent),
              textAlign: TextAlign.center,
            ),
            Text('Second',
                style: TextStyle(backgroundColor: Colors.lightGreenAccent),
                textAlign: TextAlign.center),
            Text('Third',
                style: TextStyle(backgroundColor: Colors.orangeAccent),
                textAlign: TextAlign.center),
          ],
        ),
      )),
    );
  }
}

效果如下:

image

注意,上面的Text中設定了 textAlign,但是不論設定什麼效果都是一樣的。

如果想要上面的 first、second、third 充滿螢幕的寬度,要怎麼設定呢?很簡單,直接使用Expanded包括起來即可。示例如下:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          body: Center(
        child: Row(
          children: [
            Expanded(
                child: Text('First left',
                    style: TextStyle(backgroundColor: Colors.lightBlueAccent),
                    textAlign: TextAlign.left)),
            Expanded(
                child: Text('Second center',
                    style: TextStyle(backgroundColor: Colors.lightGreenAccent),
                    textAlign: TextAlign.center)),
            Expanded(
                child: Text('Third right',
                    style: TextStyle(backgroundColor: Colors.orangeAccent),
                    textAlign: TextAlign.right)),
          ],
        ),
      )),
    );
  }
}

效果如下:

image

同樣,上面的Text設定了 textAlign,設定不同的 textAlign,會發現不同的顯示效果,對比後能發現,同時使用Expanded包括起來後,相當於三個子元素均分了螢幕寬度。

實戰#

來看一個效果,左側一個小 Icon,中間是一段很長的文案,右邊再有一個小 Icon。

現在來對比一下,下面幾種情況的顯示效果:

  1. 所有子元素都沒有Expanded的情況
  2. 所有子元素都使用Expanded的情況
  3. 中間很長的文案使用Expanded,其它子元素不用的情況

所有子元素都沒有Expanded的情況#

代碼如下:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      body: Center(
        child: Row(children: [
          const FlutterLogo(),
          const Text(
              "Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android."),
          const Icon(Icons.sentiment_satisfied),
        ]),
      ),
    ));
  }
}

效果如下:

image

可以看到左側 Icon 顯示出來了,且是原始大小;中間的文案顯示了,但是未完成;右側的 Icon 看不到。

還記得最開始說的當子元素的寬度超出時,Flutter 會顯示提示,圖片中最右側紅框標出來的部分,就是 Flutter 的提示。

所有子元素都使用Expanded的情況#

代碼如下:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      body: Center(
        child: Row(children: [
          Expanded(child: FlutterLogo()),
          Expanded(
              child: const Text(
                  "Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.")),
          Expanded(child: const Icon(Icons.sentiment_satisfied)),
        ]),
      ),
    ));
  }
}

效果如下:

image

可以看到,所有子元素都顯示出來了,且所有子元素均分了父元素的寬度,從中間文案的顯示可以看出。驗證了之前所說的,當所有子元素都使用Expaned包括時,會平均分配寬度。

中間很長的文案使用Expanded,其它子元素不用的情況#

代碼如下:


class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        home: Scaffold(
      body: Center(
        child: Row(children: [
          const FlutterLogo(),
          Expanded(
              child: const Text(
                  "Flutter's hot reload helps you quickly and easily experiment, build UIs, add features, and fix bug faster. Experience sub-second reload times, without losing state, on emulators, simulators, and hardware for iOS and Android.")),
          const Icon(Icons.sentiment_satisfied),
        ]),
      ),
    ));
  }
}

效果如下:

image

可以看出,所有子元素都顯示出來了,且,左側 Icon 和右側 Icon 的大小是按照本身的大小顯示,然後餘下的部分用於顯示了文本,且沒有超出。

參考#

Row Dev Doc
Flutter 免費視頻第三季 - 佈局

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。