Flutter開發日記——Flutter佈局Widget詳解(上)

YYDev發表於2019-11-04

Container

1、簡介

  • Container類似於h5的盒子模型,相當於佈局容器
  • Container在沒有子節點的時候,會試圖變得足夠大
  • Container在帶有子節點的時候,會根據子節點的尺寸調節自身大小

2、建構函式

Container({
    Key key,
    this.alignment,
    this.padding,
    Color color,
    Decoration decoration,
    this.foregroundDecoration,
    double width,
    double height,
    BoxConstraints constraints,
    this.margin,
    this.transform,
    this.child,
})
複製程式碼
  • alignment:控制child的對齊方式
  • padding:容器本身的內邊距
  • color:容器的背景色
  • decoration:容器的樣式,類似於css的style
  • foregroundDecoration:容器的前景色,可能會遮蓋color效果
  • width:容器的寬度
  • height:容器的高度
  • constraints:容器的約束,約束寬高的大小
  • margin:容器本身的外邊距
  • transform:容器的變換矩陣,可以讓容器的縮放、旋轉、平移等
  • child:容器的子控制元件

3、例子

decoration可以實現陰影和邊框的效果

Widget _buildColumn() {
    return Container(
      constraints: BoxConstraints.expand(
        height: 200,
      ),
      padding: EdgeInsets.all(8.0),
      child: Text("Hello World"),
      alignment: Alignment.center,
      transform: Matrix4.identity(),
      margin: EdgeInsets.all(16.0),
      decoration: BoxDecoration(
        border: Border.all(color: Colors.black, width: 2.0),
        color: Colors.blue[200],
        borderRadius: BorderRadius.circular(20.0)
      ),
      foregroundDecoration: BoxDecoration(),
      height: 200,
      width: 100,
      //color: Colors.blue[200],
    );
}
複製程式碼

在這裡插入圖片描述

Padding

1、簡介

  • Padding是比較功能單一的控制元件,負責子控制元件的內邊距

2、建構函式

const Padding({
    Key key,
    @required this.padding,
    Widget child,
})
複製程式碼
  • padding:控制元件的內邊距
  • child:子控制元件

3、例子

Widget _buildColumn() {
    return Padding(
      padding: EdgeInsets.all(8.0),
      child: Container(
        height: 200,
        width: 200,
        color: Colors.blue[200],
      ),
    );
}
複製程式碼

在這裡插入圖片描述

Align

1、簡介

  • Align可以設定child的對齊方式,例如居中、居左、居右等,並根據child尺寸調節自身尺寸
  • 當widthFactor和heightFactor為null的時候,child的尺寸會盡量的擴充套件自己的尺寸,直至填充父控制元件

2、建構函式

const Align({
    Key key,
    this.alignment: Alignment.center,
    this.widthFactor,
    this.heightFactor,
    Widget child
})
複製程式碼
  • alignment:child的對齊方式
  • widthFactor:寬度因子,若設定2.0的時候,Align的寬度將會是child的兩倍
  • heightFactor:高度因子,若設定2.0的時候,Align的高度將會是child的兩倍
  • child:子控制元件

3、例子

由於設定了heightFactor和widthFactor,表示父控制元件的寬高最大應該是子控制元件的2.0倍。如果不設定heightFactor和widthFactor,則父控制元件則無限大,則子控制元件會在螢幕底部中點

Widget _buildColumn() {
    return Container(
      color: Colors.blue[200],
      child: Align(
        heightFactor: 2.0,
        widthFactor: 2.0,
        alignment: Alignment(0.0, 1.0), //底部中點對齊
        child: Text("Hello!"),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

Center

1、簡介

  • Center控制元件是將child居中的控制元件,居中的位置是父控制元件的中點位置
  • Center控制元件若設定了heightFactor和widthFactor,則父控制元件的尺寸會有所變化
  • Center控制元件完全繼承自Align控制元件,只不過內部預設將alignment屬性設定為居中

2、建構函式

class Center extends Align {
  const Center({ Key key, double widthFactor, double heightFactor, Widget child })
    : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
複製程式碼

3、例子

由於設定了heightFactor和widthFactor,表示父控制元件的寬高最大應該是子控制元件的1.5倍,所以父控制元件大小是300x300,則子控制元件就會在父控制元件的基礎上居中顯示。如果不設定heightFactor和widthFactor,則父控制元件則無限大,填充螢幕,則Center元件就在父控制元件的居中顯示,即螢幕中間

Widget _buildColumn() {
    return Container(
      color: Colors.blueGrey,
      child: Center(
        heightFactor: 1.5,
        widthFactor: 1.5,
        child: Container(
          height: 200,
          width: 200,
          color: Colors.blue[200],
        ),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

FittedBox

1、簡介

  • FittedBox會在自己的尺寸範圍內縮放並且調整child位置,使得child適合其尺寸
  • FittedBox類似於ImageView的ScaleType的屬性

2、建構函式

const FittedBox({
    Key key,
    this.fit: BoxFit.contain,
    this.alignment: Alignment.center,
    Widget child,
})
複製程式碼
  • fit:child控制元件的填充模式
  • alignment:child的對齊方式
  • child:子控制元件

填充模式

  • BoxFit.none:預設不縮放,以子控制元件的寬和高作為基準,如果父控制元件不夠承載,則按比例縮小子控制元件,圖片不會變形
  • BoxFit.fill:將子控制元件的寬和高,填充整個父控制元件,圖片會變形
  • BoxFit.contain:將子控制元件的寬和高,按比例填充父控制元件的寬和高,直到有一邊先填充完成為止,圖片不會變形
  • BoxFit.cover:以子控制元件的寬和高作為基準,放入父控制元件中,如果父控制元件不夠承載,則裁剪子控制元件多餘的部分,圖片不會變形,但會被裁剪
  • BoxFit.fitWidth:以子控制元件的寬作為基準,放入父控制元件中,直到父控制元件的寬被擠滿,圖片不會變形,但會被裁剪
  • BoxFit.fitHeight:以子控制元件的高作為基準,放入父控制元件中,直到父控制元件的高被擠滿,圖片不會變形,但會被裁剪
  • BoxFit.scaleDown:以父控制元件的寬和高作為基準,子控制元件無條件縮放直到可以塞進父控制元件

3、例子

常用的就是對圖片的裁剪,也可以是對widget的裁剪,只要widget有固定的大小

Widget _buildColumn() {
    return Container(
      width: 300,
      height: 300,
      color: Colors.blue,
      child: FittedBox(
        fit: BoxFit.cover,
        alignment: Alignment.centerLeft,
        child: Image.asset("images/day27/girl.jpg"),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

AspectRatio

1、簡介

  • AspectRatio是調整child到設定的寬高比的元件
  • AspectRatio會根據未明確的寬或高按比例進行縮放

2、建構函式

const AspectRatio({
    Key key,
    @required this.aspectRatio,
    Widget child
}) 
複製程式碼
  • aspectRatio:縮放比例,1.0為初始比例
  • child:子控制元件

3、例子

由於高度200是確定的,寬度是不確定的,而子控制元件的縮放比是1.5,最後子控制元件的大小寬為300,高為200

Widget _buildColumn() {
    return Container(
      height: 200.0,
      color: Colors.blue,
      child: AspectRatio(
        aspectRatio: 1.5,
        child: Container(
          color: Colors.red,
        ),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

ConstrainedBox

1、簡介

  • ConstrainedBox表示對子控制元件的約束條件,可以約束子控制元件的大小

2、建構函式

ConstrainedBox({
    Key key,
    @required this.constraints,
    Widget child
})
複製程式碼
  • constraints:子控制元件的約束條件
  • child:子控制元件

3、例子

約束子控制元件最小必須是100x100,最大必須是150x150

Widget _buildColumn() {
    return ConstrainedBox(
      constraints: BoxConstraints(
        minWidth: 100.0,
        minHeight: 100.0,
        maxWidth: 150.0,
        maxHeight: 150.0,
      ),
      child: Container(
        width: 200.0,
        height: 200.0,
        color: Colors.red,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

Baseline

1、簡介

  • Baseline控制元件同文字的baseline是同個意思的,處於文字的基準線
  • 如果child有baseline(比如Text控制元件),則根據child的baseline屬性,調整child的位置
  • 如果child沒有baseline(比如Container控制元件),則根據child的bottom,來調整child的位置

2、建構函式

const Baseline({
  Key key,
  @required this.baseline,
  @required this.baselineType,
  Widget child
})
複製程式碼
  • baseline:baseline數值,自上而下
  • baselineType:baseline型別,alphabetic(對齊字元底部的水平線)和ideographic(對齊表意字元的水平線)
  • child:子控制元件

3、例子

由於文字是具有baseline屬性的,通過例子看出沒有baseline屬性的話,只能根據child的bottom對齊,文字則會在baseline上

Widget _buildColumn() {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: <Widget>[
        Baseline(
          baselineType: TextBaseline.alphabetic,
          child: Text("Java",style: TextStyle(fontSize: 20.0),),
          baseline: 50.0,
        ),
        Baseline(
          //alphabetic:對齊字元底部的水平線
          //ideographic:對齊表意字元的水平線
          baselineType: TextBaseline.alphabetic,
          child: Container(
            width: 30,
            height: 30,
            color: Colors.blue[200],
          ),
          baseline: 50.0,
        ),
        Baseline(
          baselineType: TextBaseline.alphabetic,
          child: Text("iOS",style: TextStyle(fontSize: 30.0),),
          baseline: 50.0,
        ),
      ],
    );
}
複製程式碼

在這裡插入圖片描述

FractionallySizedBox

1、簡介

  • FractionallySizedBox控制元件會根據現有空間,來調整child的尺寸
  • FractionallySizedBox控制元件中若child設定了具體的尺寸數值,也不起作用

2、建構函式

const FractionallySizedBox({
  Key key,
  this.alignment = Alignment.center,
  this.widthFactor,
  this.heightFactor,
  Widget child,
})
複製程式碼
  • alignment:child的對齊方式
  • widthFactor:寬度因子,若設定0.5的時候,子控制元件的寬度將會是父控制元件的一半,若設定1.5的時候,子控制元件的寬度將會是父控制元件的1.5倍
  • heightFactor:高度因子,若設定0.5的時候,子控制元件的高度將會是父控制元件的一半,若設定1.5的時候,子控制元件的高度將會是父控制元件的1.5倍
  • child:子控制元件

3、例子

不需要指定子控制元件的大小,通過FractionallySizedBox約束子控制元件的大小為父控制元件的一半

Widget _buildColumn() {
    return Container(
      color: Colors.blue[600],
      width: 200,
      height: 200,
      child: FractionallySizedBox(
        alignment: Alignment.center,
        widthFactor: 0.5,
        heightFactor: 0.5,
        child: Container(
          color: Colors.blue[200],
        ),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

IntrinsicHeight

1、簡介

  • IntrinsicHeight控制元件會調整child到固定的高度

2、建構函式

const IntrinsicHeight({ Key key, Widget child })
複製程式碼
  • child:子控制元件

3、例子

IntrinsicHeight子控制元件中放置四個相同寬度的容器,設定其中兩個容器的高度為150和60,另外兩個不設定,IntrinsicHeight會找到最大的高度去限制其餘容器

Widget _buildColumn() {
    return IntrinsicHeight(
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: <Widget>[
          Container(
            color: Colors.blue,
            width: 40.0,
            height: 150.0,
          ),
          Container(
            color: Colors.red,
            width: 40.0,
            height: 60.0,
          ),
          Container(color: Colors.yellow, width: 40.0),
          Container(color: Colors.yellow, width: 40.0),
        ],
      ),
    );
}
複製程式碼

在這裡插入圖片描述

IntrinsicWidth

1、簡介

  • IntrinsicWidth控制元件會調整child到固定的寬度
  • IntrinsicWidth控制元件和IntrinsicHeight控制元件最大的區別在於IntrinsicWidth的寬高會受到限制

2、建構函式

const IntrinsicWidth({ Key key, this.stepWidth, this.stepHeight, Widget child })
複製程式碼
  • stepWidth:如果為null,child的寬度是child集合當中的最大寬度,child的最小寬度為指定的stepWidth寬度,如果stepWidth寬度小於child的最小寬度,則該值不生效
  • stepHeight:如果為null,child的高度是父控制元件的最大高度,不為null,child的最大高度為指定的stepHeight高度,如果stepHeight高度小於本身父容器的高度,則該值不生效
  • child:子控制元件

3、例子

設定stepHeight為200,但是父控制元件的高度不止200,該值不生效。設定stepWidth為150,但是其他child的控制元件最大寬度不超過150,則最小的寬度為150,即圖中的灰色背景

Widget _buildColumn() {
    return Container(
      color: Colors.grey,
      child: IntrinsicWidth(
        //父容器的大小
        stepHeight: 200,
        stepWidth: 150,
        child: Column(
          children: <Widget>[
            Container(
              color: Colors.blue,
              width: 100.0,
              height: 150.0,
            ),
            Container(
              color: Colors.red,
              width: 60.0,
              height: 150.0,
            ),
            Container(color: Colors.yellow, height: 150.0),
            Container(color: Colors.green, height: 150.0),
          ],
        ),
      ),
    );
}
複製程式碼

在這裡插入圖片描述

LimitedBox

1、簡介

  • LimitedBox控制元件是對子控制元件最大寬高進行限制的控制元件
  • LimitedBox控制元件要使最大寬高限制起作用,是有一定條件的
  • 如果LimitedBox外部寬度沒有約束(比如Row,它是高度一定寬度不限制),child的寬受到LimitedBox最大寬度(maxWidth)屬性限制
  • 如果LimitedBox外部高度沒有約束(比如Column,它是寬度一定高度不限制),child的高受到LimitedBox最大高度(maxHeight)屬性限制

2、建構函式

const LimitedBox({
  Key key,
  this.maxWidth = double.infinity,
  this.maxHeight = double.infinity,
  Widget child,
})
複製程式碼
  • maxWidth:限制子控制元件的最大寬度
  • maxHeight:限制子控制元件的最大高度
  • child:子控制元件

3、例子

由於是Row元件,Row元件的高度是被確定的,寬度是不限制的,所以高度限制不起作用,寬度限制起作用,最後寬度是150,高度是250

Widget _buildColumn() {
    return Row(
      children: <Widget>[
        LimitedBox(
          maxHeight: 150, //由於是Row,高度被確定,所以高度限制不起作用
          maxWidth: 150, //由於是Row,寬度不限制,所以寬度限制起作用
          child: Container(
            width: 250,
            height: 250,
            color: Colors.redAccent,
          ),
        )
      ],
    );
}
複製程式碼

在這裡插入圖片描述

Offstage

1、簡介

  • Offstage控制元件是通過引數來控制child是否顯示

2、建構函式

const Offstage({ Key key, this.offstage = true, Widget child })
複製程式碼
  • offstage:當offstage為true,當前控制元件不會被繪製在螢幕上,不會響應點選事件,也不會佔用空間,反之相反
  • child:子控制元件

3、例子

Widget _buildColumn() {
    return Offstage(
      offstage: false,
      child: Container(
        width: 250,
        height: 250,
        color: Colors.redAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

OverflowBox

1、簡介

  • OverflowBox控制元件會限制一個範圍區域,超出最大值部分會被裁剪,低於最小值會被填充

2、建構函式

const OverflowBox({
    Key key,
    this.alignment = Alignment.center,
    this.minWidth,
    this.maxWidth,
    this.minHeight,
    this.maxHeight,
    Widget child,
})
複製程式碼
  • alignment:子控制元件的對齊方式
  • minWidth:限制子控制元件的最小寬度
  • maxWidth:限制子控制元件的最大寬度
  • minHeight:限制子控制元件的最小高度
  • maxHeight:限制子控制元件的最大高度
  • child:子控制元件

3、例子

子控制元件必須符合最小高度,所以最後出來的大小是300x600

Widget _buildColumn() {
    return OverflowBox(
      minHeight: 600,
      child: Container(
        width: 300,
        height: 300,
        color: Colors.blueAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

SizedBox

1、簡介

  • SizedBox是設定具體尺寸的控制元件

2、建構函式

const SizedBox({ Key key, this.width, this.height, Widget child })
複製程式碼
  • width:子控制元件的寬度,若設定了,會強制調整到此寬度,若未設定,則會根據子控制元件的自身的寬度進行調整
  • height:子控制元件的高度,若設定了,會強制調整到此高度,若未設定,則會根據子控制元件的自身的高度進行調整
  • child:子控制元件

3、例子

Widget _buildColumn() {
    return SizedBox(
      width: 200,
      height: 200,
      child: Container(
        color: Colors.blueAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

SizedOverflowBox

1、簡介

  • SizedOverflowBox是SizedBox與OverflowBox的結合體
  • SizedOverflowBox具有SizedBox的固定尺寸,也有OverflowBox的裁剪功能

2、建構函式

const SizedOverflowBox({
  Key key,
  @required this.size,
  this.alignment = Alignment.center,
  Widget child,
})
複製程式碼
  • size:子控制元件的尺寸
  • alignment:子控制元件的對齊方式
  • child:子控制元件

3、例子

控制child的尺寸大小為100x100

Widget _buildColumn() {
    return SizedOverflowBox(
      size: Size(100, 100),
      alignment: Alignment.center,
      child: Container(
        width: 300,
        height: 300,
        color: Colors.blueAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

Transform

1、簡介

  • Transform控制元件是控制child控制元件的矩陣變換的控制元件,通過變換矩陣,對控制元件做動畫

2、建構函式

const Transform({
  Key key,
  @required this.transform,
  this.origin,
  this.alignment,
  this.transformHitTests = true,
  Widget child,
})
複製程式碼
  • transform:矩陣變換的結果
  • origin:子控制元件的偏移位置
  • alignment:子控制元件的對齊方式
  • transformHitTests:子控制元件的點選區域是否也做相應的改變
  • child:子控制元件

3、例子

讓容器輕微的偏移上方,然後做居於自身的旋轉效果

Widget _buildColumn() {
    return Transform(
      origin: Offset(0.0, 10.0),
      transformHitTests: true,
      alignment: Alignment.center,
      transform: Matrix4.rotationZ(3.0),
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blueAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

CustomSingleChildLayout

1、簡介

  • CustomSingleChildLayout控制元件是一個可以自定義擁有單個子控制元件的佈局

2、建構函式

const CustomSingleChildLayout({
  Key key,
  @required this.delegate,
  Widget child
})
複製程式碼
  • delegate:控制子控制元件的代理類
  • child:子控制元件

3、例子

需要先建立一個代理類,將傳遞進來的引數Size作為預期尺寸,如果預期尺寸和當前子控制元件的尺寸不符合,則會重新讓子控制元件設定新的約束來適應預期Size的尺寸

class FixedSizeLayoutDelegate extends SingleChildLayoutDelegate {
  FixedSizeLayoutDelegate(this.size);
  // 預期尺寸
  final Size size;

  @override
  Size getSize(BoxConstraints constraints) => size;

  @override
  BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
    // 重新設定子控制元件的約束,讓他適應預期Size的尺寸
    return BoxConstraints.tight(size);
  }

  @override
  bool shouldRelayout(FixedSizeLayoutDelegate oldDelegate) {
    // 如果預期尺寸和當前子控制元件的尺寸不符合,則重新layout
    return size != oldDelegate.size;
  }
}
複製程式碼

由於預期的尺寸是300x300,當前尺寸和預期不匹配,所以會將子控制元件調整到預期的尺寸

Widget _buildColumn() {
    return CustomSingleChildLayout(
      delegate: FixedSizeLayoutDelegate(Size(300, 300)),
      child: Container(
        width: 100,
        height: 100,
        color: Colors.blueAccent,
      ),
    );
}
複製程式碼

在這裡插入圖片描述

作者

Flutter開發日記——Flutter佈局Widget詳解(上)
Hensen_

相關文章