Flutter 系列文章:Flutter Column 控制元件介紹

sometime-rock發表於2019-03-19

Column —— 行佈局

一、使用方法

  Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,//設定主軸方向上的對齊方式
    MainAxisSize mainAxisSize = MainAxisSize.max,//設定主軸方向佔有空間的值,預設是max (MainAxisSize的取值有兩種:max:根據傳入的佈局約束條件,最大化主軸方向的可用空間;min:與max相反,是最小化主軸方向的可用空間;)
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,//設定交叉軸方向上的對齊方式
    TextDirection textDirection,//設定文字的排列方向,可以通過在設定Row主軸的基礎上設定 改變主軸的方向
    VerticalDirection verticalDirection = VerticalDirection.down,//設定主軸的基礎上,可以通過設定verticalDirection改變主軸的方向
    TextBaseline textBaseline,//設定
    List<Widget> children = const <Widget>[],//子控制元件列表
  }) 
複製程式碼
1. 用於在垂直方向中顯示其子項,另通過
        //todo 例子1. Column,用於在垂直方向中顯示其子項。
        Column(
          children: <Widget>[
            //Expanded 用於展開Row,Column或Flex的子項的視窗小部件。
            //使用“ Expanded”小部件可以擴充套件行,列或Flex的子項 以填充主軸中的可用空間(例如,水平為行或垂直為列)。如果擴充套件了多個子節點,則根據彈性因子將可用空間劃分為多個子節點。
            Expanded(
              //建構函式 擴充套件({ Key key, int flex:1, @required Widget child })
              //@required  child 為必填引數,指要填充的子控制元件
              child: Text('Deliver features faster', textAlign: TextAlign.center),
//              child: Text('Deliver ', textAlign: TextAlign.center),
              //孩子最多可以與可用空間一樣大(但允許更小)
              flex: 1,
              //鍵
              key: ValueKey("1"),
            ),
            Expanded(
              child: Text('Craft beautiful', textAlign: TextAlign.center),
              //通過還在控制元件去強制填充可以用空間,會向兩邊擠壓,以適應這個子控制元件
              flex: 1,
            ),
            Expanded(
              flex: 2,
              child: FittedBox(
                fit: BoxFit.contain, // otherwise the logo will be tiny
                child: const FlutterLogo(),
              ),
            ),
          ],
        )

複製程式碼

image

2. 為什麼我的列有黃色和黑色警告條紋?

如果列非靈活內容(那些未包含在 Expanded或Flexible小部件中的內容)在一起比列本身寬,則說該列已溢位。當列溢位時,該列沒有任何剩餘空間可在其Expanded和Flexible 子級之間共享。該列通過在溢位的邊緣上繪製黃色和黑色條紋警告框來報告此情況。如果列外側有空間,則溢位量以紅色字型列印。

        //例子2 為什麼我的列有黃色和黑色警告條紋
          Column(
            children: <Widget>[
              const FlutterLogo(
                size: 200,
              ),
              const Icon(
                Icons.account_circle,
                size: 300,
                color: Colors.blue,
              ),
              const Icon(
                Icons.ac_unit,
                size: 200,
                color: Colors.yellow,
              )
            ],
          )
複製程式碼

image

3. 通過Expanded 包裹自適應均分分佈

可以解決例子2中的問題,將第二個子項包裝在Expanded小部件中,該小部件告訴列應該為該子項提供剩餘空間:

          //例子3 通過Expanded 包裹自適應均分分佈
          //解決方法 解決方法是將第二個子項包裝在Expanded小部件中,該小部件告訴該列應該為該子項提供剩餘空間:
          Column(
            children: <Widget>[
              const Expanded(
                flex: 1,
                  child: FittedBox(
                    fit: BoxFit.contain,
                    child: const FlutterLogo(),
                  )
              ),
              const Expanded(
                flex: 1,
                child: Icon(
                Icons.account_circle,
                size: 300,
                color: Colors.blue,
               ),
              ),
               Expanded(
                 flex: 1,
                child: Icon(
                  Icons.access_time,
                  size: 300,
                  color: Colors.yellow,
                ),
              ),
            ],
          )
複製程式碼

image

二、常用屬性

1. 設定主軸方向上的對齊方式 —— mainAxisAlignment
  • 在水平方向控制元件(Row):

  • MainAxisAlignment是水平的,預設起始位置在左邊,排列方向為從左至右,此時可以通過textDirection來改變MainAxisAlignment的起始位置和排列方向

  • 在垂直方向的控制元件中(Column) :

  • MainAxisAlignment是垂直的,預設起始位置在上邊,排列方向為從上至下,此時可以通過verticalDirection來改變MainAxisAlignment的起始位置及排列方向

  • MainAxisAlignment 的列舉型別

    enum MainAxisAlignment {

      //將子控制元件放在主軸的開始位置
      start,

      //將子控制元件放在主軸的結束位置
      end,

      //將子控制元件放在主軸的中間位置
      center,

      //將主軸空白位置進行均分,排列子元素,手尾沒有空隙
      spaceBetween,

      //將主軸空白區域均分,使中間各個子控制元件間距相等,首尾子控制元件間距為中間子控制元件間距的一半
      spaceAround,

      //將主軸空白區域均分,使各個子控制元件間距相等
      spaceEvenly,
    }

複製程式碼
  • 例子
          // 例子5
          Column(
            mainAxisAlignment: MainAxisAlignment.start,
            //todo 在設定Column主軸的基礎上,可以通過設定verticalDirection改變主軸的方向,
            // verticalDirection的預設值為VerticalDirection.down,也就是從上至下的方向
            // verticalDirection的預設值為VerticalDirection.up,也就是從下至上的方向
            verticalDirection:VerticalDirection.down,
            children: <Widget>[
              Box("aaaaaaa"),
              Box("bbbbbbb"),
              Box("ccccccc")
            ],

          )
複製程式碼

image

2. 設定交叉軸方向上的對齊方式 —— crossAxisAlignment
  • 在水平方向控制元件(Row):

  • CrossAxisAlignment是垂直的,預設起始位置在中間,排列方向為從上至下,此時可以通過verticalDirection來改變CrossAxisAlignment的起始位置及排列方向

  • 在垂直方向的控制元件中(Column) :

  • CrossAxisAlignment是水平的,預設起始位置在中間,此時可以通過textDirection來改變CrossAxisAlignment的起始位置

  • 列舉型別

  enum CrossAxisAlignment {
      //將子控制元件放在交叉軸的起始位置
      start,

      //將子控制元件放在交叉軸的結束位置
      end,

      //將子控制元件放在交叉軸的中間位置
      center,

    //使子控制元件填滿交叉軸
      stretch,

    //將子控制元件放在交叉軸的上,並且與基線相匹配(不常用)
      baseline,
      
    }
複製程式碼
  • 例子
        //例子 7 在column的基礎上設定交叉軸
        Column(
            mainAxisAlignment: MainAxisAlignment.start,
            //todo 預設為start 將子控制元件放在交叉軸的起始位置
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              Box("aaaaaaa"),
              Box("bbbbbbb"),
              Box("ccccccc"),
              Expanded(
                flex: 2,
                child: Text('Column crossAxisAlignment .'),
              )
        ],
      )
複製程式碼

image

3. 在設定Column主軸的基礎上,可以通過設定verticalDirection改變主軸的方向
        // verticalDirection的預設值為VerticalDirection.down,也就是從上至下的方向
        // verticalDirection的預設值為VerticalDirection.up,也就是從下至上的方向
複製程式碼
          // 例子5
          Column(
            mainAxisAlignment: MainAxisAlignment.start,
            //todo 在設定Column主軸的基礎上,可以通過設定verticalDirection改變主軸的方向,
            // verticalDirection的預設值為VerticalDirection.down,也就是從上至下的方向
            // verticalDirection的預設值為VerticalDirection.up,也就是從下至上的方向
            verticalDirection:VerticalDirection.down,
            children: <Widget>[
              Box("aaaaaaa"),
              Box("bbbbbbb"),
              Box("ccccccc")
            ],

          )
複製程式碼

image

三、一個完整的例子

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ColumnPageDemo(title: 'FlexPageDemo'),
    );
  }
}

class ColumnPageDemo extends StatefulWidget {
  ColumnPageDemo({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _ColumnPageDemoState createState() => _ColumnPageDemoState();
}

class _ColumnPageDemoState extends State<ColumnPageDemo> {
  void _incrementCounter() {
    setState(() {
    });
  }

  //描述此視窗小部件表示的使用者介面部分
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        //todo 這裡有個要注意的點就是如果父控制元件沒有設定大小,container預設是用子控制元件的大小去填充父控制元件的大小
          height:MediaQuery.of(context).size.height, //獲取螢幕的高度
          width: MediaQuery.of(context).size.width,//獲取螢幕的寬度,
          child:

          //todo 例子1. Column,用於在垂直方向中顯示其子項。
//        Column(
//          children: <Widget>[
//            //Expanded 用於展開Row,Column或Flex的子項的視窗小部件。
//            //使用“ Expanded”小部件可以擴充套件列,列或Flex的子項 以填充主軸中的可用空間(例如,水平為列或垂直為列)。如果擴充套件了多個子節點,則根據彈性因子將可用空間劃分為多個子節點。
//            Expanded(
//              //建構函式 擴充套件({ Key key, int flex:1, @required Widget child })
//              //@required  child 為必填引數,指要填充的子控制元件
//              child: Text('Deliver features faster', textAlign: TextAlign.center),
////              child: Text('Deliver ', textAlign: TextAlign.center),
//              //孩子最多可以與可用空間一樣大(但允許更小)
//              flex: 1,
//              //鍵
//              key: ValueKey("1"),
//            ),
//            Expanded(
//              child: Text('Craft beautiful', textAlign: TextAlign.center),
//              //通過還在控制元件去強制填充可以用空間,會向兩邊擠壓,以適應這個子控制元件
//              flex: 1,
//            ),
//            Expanded(
//              flex: 2,
//              child: FittedBox(
//                fit: BoxFit.contain, // otherwise the logo will be tiny
//                child: const FlutterLogo(),
//              ),
//            ),
//          ],
//        )

          //todo 例子2 為什麼我的列有黃色和黑色警告條紋?
          //如果列非靈活內容(那些未包含在 Expanded或Flexible小部件中的內容)在一起比列本身寬,則說該列已溢位。當列溢位時,該列沒有任何剩餘空間可在其Expanded和Flexible 子級之間共享。該列通過在溢位的邊緣上繪製黃色和黑色條紋警告框來報告此情況。如果列外側有空間,則溢位量以紅色字型列印。
//          Column(
//            children: <Widget>[
//              const FlutterLogo(
//                size: 200,
//              ),
//              const Icon(
//                Icons.account_circle,
//                size: 300,
//                color: Colors.blue,
//              ),
//              const Icon(
//                Icons.ac_unit,
//                size: 200,
//                color: Colors.yellow,
//              )
//            ],
//          )

          //todo 例子3 通過Expanded 包裹自適應均分分佈
          //解決方法 解決方法是將第二個子項包裝在Expanded小部件中,該小部件告訴該列應該為該子項提供剩餘空間:
          Column(
            children: <Widget>[
              const Expanded(
                flex: 1,
                  child: FittedBox(
                    fit: BoxFit.contain,
                    child: const FlutterLogo(),
                  )
              ),
              const Expanded(
                flex: 1,
                child: Icon(
                Icons.account_circle,
                size: 300,
                color: Colors.blue,
               ),
              ),
               Expanded(
                 flex: 1,
                child: Icon(
                  Icons.access_time,
                  size: 300,
                  color: Colors.yellow,
                ),
              ),
            ],
          )


          //todo 例子4 MainAxisAlignment和CrossAxisAlignment詳解
          //MainAxisAlignment(主軸)就是與當前控制元件方向一致的軸,而CrossAxisAlignment(交叉軸)就是與當前控制元件方向垂直的軸
          //在水平方向控制元件中,Row
          //MainAxisAlignment是水平的,預設起始位置在左邊,排列方向為從左至右,此時可以通過textDirection來改變MainAxisAlignment的起始位置和排列方向
          //CrossAxisAlignment是垂直的,預設起始位置在中間,排列方向為從上至下,此時可以通過verticalDirection來改變CrossAxisAlignment的起始位置及排列方向

          //在垂直方向的控制元件中,Column
          //MainAxisAlignment是垂直的,預設起始位置在上邊,排列方向為從上至下,此時可以通過verticalDirection來改變MainAxisAlignment的起始位置及排列方向
          //CrossAxisAlignment是水平的,預設起始位置在中間,此時可以通過textDirection來改變CrossAxisAlignment的起始位置


//      enum MainAxisAlignment {
//
//      //將子控制元件放在主軸的開始位置
//      start,
//
//      //將子控制元件放在主軸的結束位置
//      end,
//
//      //將子控制元件放在主軸的中間位置
//      center,
//
//      //將主軸空白位置進列均分,排列子元素,手尾沒有空隙
//      spaceBetween,
//
//      //將主軸空白區域均分,使中間各個子控制元件間距相等,首尾子控制元件間距為中間子控制元件間距的一半
//      spaceAround,
//
//      //將主軸空白區域均分,使各個子控制元件間距相等
//      spaceEvenly,
//      }

//       在設定主軸的基礎上設定 主軸的方向
//       textDirection:TextDirection.rtl:從右到左
//       textDirection:TextDirection.ltr:從左到右

//      例子4.1
//          Row(
//        mainAxisAlignment: MainAxisAlignment.start,
//        //todo  在設定Row主軸的基礎上設定 改變主軸的方向
////        textDirection:TextDirection.rtl,
//        children: <Widget>[
//          Box("aaaaaaa"),
//          Box("bbbbbbb"),
//          Box("ccccccc")
//        ],
//      )

          ////      例子4.2
//          Column(
//            mainAxisAlignment: MainAxisAlignment.start,
//            //todo 在設定Column主軸的基礎上,可以通過設定verticalDirection改變主軸的方向,
//            // verticalDirection的預設值為VerticalDirection.down,也就是從上至下的方向
//            // verticalDirection的預設值為VerticalDirection.up,也就是從下至上的方向
//            verticalDirection:VerticalDirection.down,
//            children: <Widget>[
//              Box("aaaaaaa"),
//              Box("bbbbbbb"),
//              Box("ccccccc")
//            ]
//          )

          // 例子5
//          Column(
//            mainAxisAlignment: MainAxisAlignment.start,
//            //todo 在設定Column主軸的基礎上,可以通過設定verticalDirection改變主軸的方向,
//            // verticalDirection的預設值為VerticalDirection.down,也就是從上至下的方向
//            // verticalDirection的預設值為VerticalDirection.up,也就是從下至上的方向
//            verticalDirection:VerticalDirection.down,
//            children: <Widget>[
//              Box("aaaaaaa"),
//              Box("bbbbbbb"),
//              Box("ccccccc")
//            ],
//
//          )

//todo      enum CrossAxisAlignment {
//      //將子控制元件放在交叉軸的起始位置
//      start,
//
//      //將子控制元件放在交叉軸的結束位置
//      end,
//
//      //將子控制元件放在交叉軸的中間位置
//      center,
//
////使子控制元件填滿交叉軸
//      stretch,
//
////將子控制元件放在交叉軸的上,並且與基線相匹配(不常用)
//      baseline,
//      }

        //例子 6 在row的基礎上設定交叉軸
//          Row(
//            mainAxisAlignment: MainAxisAlignment.start,
//            //todo 預設為start 將子控制元件放在交叉軸的起始位置
//            crossAxisAlignment: CrossAxisAlignment.stretch,
//            children: <Widget>[
//              Box("aaaaaaa"),
//              Box("bbbbbbb"),
//              Box("ccccccc")
//            ],
//          )

        //例子 7 在column的基礎上設定交叉軸
//        Column(
//            mainAxisAlignment: MainAxisAlignment.start,
////            //todo 預設為start 將子控制元件放在交叉軸的起始位置
//            crossAxisAlignment: CrossAxisAlignment.start,
//            children: <Widget>[
//              Box("aaaaaaa"),
//              Box("bbbbbbb"),
//              Box("ccccccc"),
//              Expanded(
//                flex: 2,
//                child: Text('Column crossAxisAlignment .'),
//              )
//        ],
//      )

      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

/**
 *  寫一個矩形
 */
class Box extends StatelessWidget{
  String mStr="";
  Box(@required String str){
    this.mStr = str;
  }
  @override
  Widget build(BuildContext context) {
    return Container(
      width: 80,
      height: 80,
      alignment: Alignment.center,
      color: Colors.teal.shade300,
      child: Text(mStr),
      foregroundDecoration: BoxDecoration(
          border: Border.all(
            color: Colors.black,
            width: 1,
          )
      ),
    );
  }

}


複製程式碼

相關文章