Flutter之容器類Widget

Flutter

  • Flutter和Dart系列文章
  • 項目GitHub地址
  • 容器類Widget和佈局類Widget都做用於其子Widget,不一樣的是:
    • 佈局類Widget通常都須要接收一個widget數組(children),他們直接或間接繼承自(或包含)MultiChildRenderObjectWidget
    • 而容器類Widget通常只須要接受一個子Widgetchild),他們直接或間接繼承自(或包含)SingleChildRenderObjectWidget
    • 佈局類Widget是按照必定的排列方式來對其子Widget進行排列
    • 而容器類Widget通常只是包裝其子Widget,對其添加一些修飾(補白或背景色等)、變換(旋轉或剪裁等)、或限制(大小等)。
  • Flutter官方並無對Widget進行官方分類,咱們對其分類主要是爲了方便討論和對Widget功能的區分記憶
  • 相關容器類Widget主要分爲如下幾種
    • 填充類容器Padding
    • 佈局限制類容器ConstrainedBoxSizeBox
    • 裝飾類容器DecoratedBox
    • 變換類容器Transform
    • 組合容器Container
    • 導航類容器ScaffoldTabBarAppBar

Padding

Padding能夠給其子元素設置內邊距git

class Padding extends SingleChildRenderObjectWidget {
    const Padding({
        Key key,
        // 內邊距
        @required this.padding,
        Widget child,
    })
    
    final EdgeInsetsGeometry padding;
}
複製代碼

EdgeInsetsGeometry是一個抽象類,通常狀況都使用EdgeInsets,它是EdgeInsetsGeometry的一個子類, 下面是的定義的一些方法github

class EdgeInsets extends EdgeInsetsGeometry {
    // 根據上下左右分別設置邊距
    const EdgeInsets.fromLTRB(this.left, this.top, this.right, this.bottom);

    // 統一設置四周邊距
    const EdgeInsets.all(double value)
    
    // 只設置其中某幾個邊距
    const EdgeInsets.only({
        // 下面的都是默認值
        this.left = 0.0,
        this.top = 0.0,
        this.right = 0.0,
        this.bottom = 0.0
    });
    
    // 根據水平和垂直方向設置, 上下間距同樣, 左右間距同樣
    const EdgeInsets.symmetric({ double vertical = 0.0,
                             double horizontal = 0.0 })
                             
    // 靜態變量, 上下左右, 都是0
    static const EdgeInsets zero = EdgeInsets.only();
}
複製代碼

示例數組

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: EdgeInsets.all(20),
      child: Icon(Icons.phone, color: Colors.cyan,),
    );
  }
}
複製代碼

ConstrainedBox

  • ConstrainedBoxSizedBox都是經過RenderConstrainedBox來渲染的
  • SizedBox只是ConstrainedBox一個定製
  • ConstrainedBox主要用於對子widget添加額外的約束
class ConstrainedBox extends SingleChildRenderObjectWidget {
  
  ConstrainedBox({
    Key key,
    @required this.constraints,
    Widget child
  })

  /// 給子widget添加約束
  final BoxConstraints constraints;
複製代碼

BoxConstraints

BoxConstraints設置Widget的約束, 內部設置了四個屬性: 最大/小寬度和最大小高度, 下面是其相關構造函數和實例函數bash

class BoxConstraints extends Constraints {
  /// 構造函數
  const BoxConstraints({
    // 最小寬度
    this.minWidth = 0.0,
    // 最大寬度
    this.maxWidth = double.infinity,
    // 最小高度
    this.minHeight = 0.0,
    // 最大高度
    this.maxHeight = double.infinity
  });

  /// 根據指定的Size設置約束
  BoxConstraints.tight(Size size)
    : minWidth = size.width,
      maxWidth = size.width,
      minHeight = size.height,
      maxHeight = size.height;

  // 根據指定的寬高設置, 參數可爲空
  const BoxConstraints.tightFor({
    double width,
    double height
  }): minWidth = width != null ? width : 0.0,
      maxWidth = width != null ? width : double.infinity,
      minHeight = height != null ? height : 0.0,
      maxHeight = height != null ? height : double.infinity;

  // 默認寬高都是最大值, 參數可爲空
  const BoxConstraints.tightForFinite({
    double width = double.infinity,
    double height = double.infinity
  }): minWidth = width != double.infinity ? width : 0.0,
      maxWidth = width != double.infinity ? width : double.infinity,
      minHeight = height != double.infinity ? height : 0.0,
      maxHeight = height != double.infinity ? height : double.infinity;

  // 根據Size參數, 設置其最大值, 最小值爲0
  BoxConstraints.loose(Size size)
    : minWidth = 0.0,
      maxWidth = size.width,
      minHeight = 0.0,
      maxHeight = size.height;
      
  // 根據寬高設置, 若是參數爲空則默認爲最大值
  const BoxConstraints.expand({
    double width,
    double height
  }): minWidth = width != null ? width : double.infinity,
      maxWidth = width != null ? width : double.infinity,
      minHeight = height != null ? height : double.infinity,
      maxHeight = height != null ? height : double.infinity;
}
複製代碼

使用實例微信

class ConstrainedBoxView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return ConstrainedBox(
      constraints: BoxConstraints(
        minWidth: double.infinity,  // 寬度設置最大
        minHeight: 50,    // 高度最小值設置50
      ),
      child: Container(
        height: 10,   // 設置高度爲10
        child: DecoratedBox(decoration: BoxDecoration(color: Colors.orange)),
      ),
    );
  }
}
複製代碼

image

  • 能夠看到, 雖然將Container的高度設置爲10像素,可是最終倒是50像素,這正是ConstrainedBox的最小高度限制生效了
  • 若是將Container的高度設置爲80像素,那麼最終紅色區域的高度也會是80像素,由於在此示例中,ConstrainedBox只限制了最小高度,並未限制最大高度

SizedBox

SizedBox用於給子widget指定固定的寬高markdown

// SizedBox的幾種構造函數
class SizedBox extends SingleChildRenderObjectWidget {
  /// 設置固定的高度
  const SizedBox({ Key key, this.width, this.height, Widget child })
    : super(key: key, child: child);

  /// 建立一個最大寬高的box
  const SizedBox.expand({ Key key, Widget child })
    : width = double.infinity,
      height = double.infinity,
      super(key: key, child: child);

  /// 建立一個最小寬高(都是0)的box
  const SizedBox.shrink({ Key key, Widget child })
    : width = 0.0,
      height = 0.0,
      super(key: key, child: child);

  /// 建立一個指定size 的box
  SizedBox.fromSize({ Key key, Widget child, Size size })
    : width = size?.width,
      height = size?.height,
      super(key: key, child: child);
}
複製代碼

這裏咱們建立一個指定寬高的Widgetless

class SizedBoxView extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return SizedBox(
      width: 80,
      height: 80,
      child: Container(
        child: DecoratedBox(decoration: BoxDecoration(color: Colors.orange)),
      ),
    );
  }
}

// 實際上SizedBox和只是ConstrainedBox一個定製, 上面的代碼等價於
ConstrainedBox(
  constraints: BoxConstraints.tightFor(width: 80.0,height: 80.0),
  child: Container(
    child: DecoratedBox(decoration: BoxDecoration(color: Colors.orange)),
  ),
)
複製代碼

而實際上ConstrainedBoxSizedBox都是經過RenderConstrainedBox來渲染的,咱們能夠看到ConstrainedBoxSizedBoxcreateRenderObject()方法都返回的是一個RenderConstrainedBox對象ide

// SizedBox
class SizedBox extends SingleChildRenderObjectWidget {
 RenderConstrainedBox createRenderObject(BuildContext context) {
    return RenderConstrainedBox(
      additionalConstraints: _additionalConstraints,
    );
  }

  BoxConstraints get _additionalConstraints {
    return BoxConstraints.tightFor(width: width, height: height);
  }
}

// ConstrainedBox
class ConstrainedBox extends SingleChildRenderObjectWidget {
  RenderConstrainedBox createRenderObject(BuildContext context) {
    return RenderConstrainedBox(additionalConstraints: constraints);
  }

  final BoxConstraints constraints;
}
複製代碼

多重限制問題函數

  • 若是某一個widget有多個父ConstrainedBox限制
  • 對於minWidthminHeight來講,是取父子中相應數值較大的。只有這樣才能保證父限制與子限制不衝突
  • 對於maxWidthmaxHeight來講, 無效, 最終寬高都是0

UnconstrainedBox

const UnconstrainedBox({
    Key key,
    Widget child,
    // TextDirection, 表示水平方向子widget的佈局順序
    this.textDirection,
    // 子Widget在主軸上的對其方式
    this.alignment = Alignment.center,
    // 設置約束的軸, 水平or垂直, Axis.horizontal
    this.constrainedAxis,
})
複製代碼
  • UnconstrainedBox不會對子Widget產生任何限制,它容許其子Widget按照其自己大小繪製
  • 通常狀況下,咱們會不多直接使用此widget,但在"去除"多重限制的時候也許會有幫助
ConstrainedBox(
  constraints: BoxConstraints(
    minWidth: 60,
    minHeight: 100,
  ),
  child: UnconstrainedBox(  // 「去除」父級限制
    textDirection: TextDirection.ltr,
    alignment: Alignment.center,
    constrainedAxis: Axis.horizontal,
    child: ConstrainedBox(
      constraints: BoxConstraints(
        minWidth: 90,
        minHeight: 20,
      ),
      child: DecoratedBox(decoration: BoxDecoration(color: Colors.red)),
    ),
  )
);
複製代碼
  • 上面代碼中,若是沒有中間的UnconstrainedBox,那麼根據上面所述的多重限制規則,那麼最終將顯示一個90×100的紅色框
  • 可是因爲UnconstrainedBox「去除」了父ConstrainedBox的限制,則最終會按照子ConstrainedBox的限制來繪製紅色框,即90×20:

image

  • 可是須要注意,UnconstrainedBox對父限制的「去除」並不是是真正的去除,上面例子中雖然紅色區域大小是90×20,但上方仍然有80的空白空間。
  • 也就是說父限制的minHeight(100.0)仍然是生效的,只不過它不影響最終子元素的大小,但仍然仍是佔有相應的空間,能夠認爲此時的父ConstrainedBox是做用於子ConstrainedBox上,而紅色框只受子ConstrainedBox限制,這一點請讀者務必注意
  • 而且目前沒有什麼方式可以完全去除父BoxConstraints的限制
  • 在定義一個通用的widget時,若是對子widget指定限制時必定要注意,由於一旦指定限制條件,子widget若是要進行相關自定義大小時將可能很是困難,由於子widget在不更改父widget的代碼的狀況下沒法完全去除其限制條件

DecoratedBox

DecoratedBox能夠在其子widget繪製前(或後)繪製一個裝飾Decoration(如背景、邊框、漸變等), 構造函數以下佈局

const DecoratedBox({
    Key key,
    @required this.decoration,
    this.position = DecorationPosition.background,
    Widget child
})
複製代碼
  • decoration: 表明將要繪製的裝飾,它類型爲Decoration是一個抽象類,它定義了一個接口 createBoxPainter(),子類的主要職責是須要經過實現它來建立一個裝飾器, 因此後面咱們將使用BoxDecoration來實現該屬性
  • position:此屬性決定在哪裏繪製Decoration,它接收DecorationPosition的枚舉類型,該枚舉類兩個值:
    • background:在子widget以後繪製,即背景裝飾(是默認值)
    • foreground:在子widget之上繪製,即前景

BoxDecoration

BoxDecoration是一個Decoration的子類, 一般咱們都是使用它來實現上面的相似decoration的相關屬性

const BoxDecoration({
    // 背景顏色
    this.color,
    // 背景圖片, DecorationImage
    this.image,
    // 邊框
    this.border,
    // 圓角
    this.borderRadius,
    // 陰影
    this.boxShadow,
    // 漸變色
    this.gradient,
    // 背景顏色和背景圖片的混合渲染模式`BlendMode`, 下面會介紹該枚舉值
    this.backgroundBlendMode,
    // 形狀
    this.shape = BoxShape.rectangle,
})
複製代碼

image

設置背景圖片DecorationImage

const DecorationImage({
    // ImageProvider類型
    @required this.image,
    this.colorFilter,
    this.fit,
    this.alignment = Alignment.center,
    this.centerSlice,
    this.repeat = ImageRepeat.noRepeat,
    this.matchTextDirection = false,
})
複製代碼

image

  • 圖片的設置方式, 是ImageProvider類型的
  • ImageProvider是一個抽象類, 須要使用其子類實現
    • NetworkImage
    • FileImage
    • MemoryImage

colorFilter

  • 在繪製圖像以前應用於圖像的濾色器, 這個屬性值是ColorFilter
  • ColorFilter的構造方法中有兩個屬性, 分別設置顏色圖像和圖片圖像, 後面也將使用這兩個名詞解釋各個枚舉值
// 兩個屬性, 分別設置顏色圖像和圖片圖像
const ColorFilter.mode(Color color, BlendMode blendMode)
複製代碼

BlendMode有如下枚舉值, 帶有src表示圖片圖像不顯示, dst表示顏色圖像不顯示

blendMode 枚舉值意義
clear 顏色圖像和圖片圖像都不顯示
src 顯示顏色圖像不顯示圖片圖像
dst 顯示圖片圖像不顯示顏色圖像
srcOver 顏色圖像在圖片圖像的上面
dstOver 顏色圖像在圖片圖像的下面
srcIn 顯示圖片圖像, 但只顯示和顏色圖像重合的部分(二者的交集)
dstIn 顯示顏色圖像, 但只顯示和圖片圖像重合的部分(二者的交集)
srcOut 顯示圖片圖像, 但只顯示和顏色圖像不重合的部分(二者的差集)
dstOut 顯示顏色圖像, 但只顯示和圖片圖像不重合的部分(二者的差集), 通常都是空了
srcATop 將圖片圖像合成到顏色圖像上面, 只合成交集的部分
dstATop 將顏色圖像合成到圖片圖像上面, 只合成交集的部分
xor 圖片圖像和顏色圖像合成的結果
plus 圖片和顏色的合成, 可是會受透明度的影響
modulate 將圖片圖像和顏色圖像的顏色份量相乘。這隻能產生相同或較暗的顏色(乘以白色,1.0,結果不變;乘以黑色,0.0,結果爲黑色
screen 將圖片圖像和顏色圖像的顏色份量的倒數相乘, 並反轉結果
overlay 在調整圖片圖像和顏色圖像的組件以使其有利於目標以後,將其相乘
darken 經過從每一個顏色通道中選擇最低值來合成圖片圖像和顏色圖像
lighten 經過從每一個顏色通道中選擇最高值來合成圖片圖像和顏色圖像

除此以外還有好幾個枚舉值, 可是我確實不知道該怎麼解釋了, 上面的解釋好像也不是很清晰, 模模糊糊, 仍是建議你們自測看效果圖吧, 或者看看官方文檔, 也有效果圖, 其實不少枚舉值仍是用不到的, 若是有比較好的解釋的話, 歡迎你們多多提出建議.........大寫的尷尬

border

設置邊框的樣式,BoxBorder是一個抽象類, 有如下兩個類共三種實現方式

// Border的兩種實現方式
class Border extends BoxBorder {
  const Border({
    this.top = BorderSide.none,
    this.right = BorderSide.none,
    this.bottom = BorderSide.none,
    this.left = BorderSide.none,
  })
  
  factory Border.all({
    Color color = const Color(0xFF000000),
    double width = 1.0,
    BorderStyle style = BorderStyle.solid,
  })
}

// 下面是BorderSide的構造函數, 以前的文字中都介紹過, 這裏就不在說起了
class BorderSide {
  const BorderSide({
    this.color = const Color(0xFF000000),
    this.width = 1.0,
    this.style = BorderStyle.solid,
  })
}

// BorderDirectional的構造函數
class BorderDirectional extends BoxBorder {
  const BorderDirectional({
    this.top = BorderSide.none,
    this.start = BorderSide.none,
    this.end = BorderSide.none,
    this.bottom = BorderSide.none,
  })
}
複製代碼

boxShadow

設置盒子的陰影, 這個陰影和盒子的形狀保持一致, 接受的值是一個存儲BoxShadow的列表, 下面下看一下BoxShadow的構造函數

const BoxShadow({
    // 顏色
    Color color = const Color(0xFF000000),
    // 陰影相對於盒子的偏移量
    Offset offset = Offset.zero,
    // 陰影的模糊程度, 值越大陰影越模糊
    double blurRadius = 0.0,
    // 陰影向相反方向增長的像素值
    this.spreadRadius = 0.0
})

// 演示示例, 四個邊都添加陰影
[
    BoxShadow(color: Colors.grey, offset: Offset(-5, -5), blurRadius: 10, spreadRadius: 0),
    BoxShadow(color: Colors.red, offset: Offset(5, 5), blurRadius: 10, spreadRadius: 0),
],
複製代碼

gradient

設置背景顏色爲漸變色, Gradient又是一個抽象類, 以下一共有三個子類

  • LinearGradient
  • RadialGradient
  • SweepGradient
// 線性漸變
const LinearGradient({
    // 起始點
    this.begin = Alignment.centerLeft,
    // 終點
    this.end = Alignment.centerRight,
    // 色值數組
    @required List<Color> colors,
    // 值列表,裝有0.0到1.0的數值
    List<double> stops,
    // 漸變平鋪模式,指定在開始和結束之外的區域平鋪模式
    this.tileMode = TileMode.clamp,
})

// 圓形漸變, 
const RadialGradient({
    // 漸變的中心)
    this.center = Alignment.center,
    // 漸變的半徑,浮點型,具體數值須要乘以盒子的寬度
    this.radius = 0.5,
    @required List<Color> colors,
    List<double> stops,
    this.tileMode = TileMode.clamp,
    this.focal,
    this.focalRadius = 0.0
})

const SweepGradient({
    // 位置的中心點
    this.center = Alignment.center,
    // 起始點的角度
    this.startAngle = 0.0,
    // 終點的角度
    this.endAngle = math.pi * 2,
    @required List<Color> colors,
    List<double> stops,
    this.tileMode = TileMode.clamp,
})
複製代碼

三種漸變色效果以下所示

image

LinearGradient線性漸變色下, 漸變模式TileMode各枚舉值對應的效果以下

image

shape

設置背景的形狀, 針對背景色, 背景圖片和漸變色, BoxShape類型是個枚舉值

enum BoxShape {
  // 保持不變
  rectangle,

  // 剪切成圓形, 和borderRadius屬性衝突
  circle,
}
複製代碼

Transform

  • Transform能夠在其子Widget繪製時對其進行一個矩陣變換, 能夠對child作平移、旋轉、縮放等操做
  • Matrix4是一個4D矩陣,經過它能夠實現各類矩陣操做

Transform

先來看下Transform的一些構造函數吧

class Transform extends SingleChildRenderObjectWidget {
  // 建立一個矩陣變換Widget
  const Transform({
    Key key,
    // 矩陣執行的變換操做, 接受一個Matrix4對象
    @required this.transform,
    
    // 旋轉點,相對於左上角頂點的偏移。默認旋轉點事左上角頂點, 
    // 接受一個Offset對象
    this.origin,
    // 對其方式
    this.alignment,
    // 點擊區域是否也作相應的改變
    this.transformHitTests = true,
    Widget child,
  })
  
  // 建立一個旋轉變換矩陣
  Transform.rotate({
    Key key,
    // 設置旋轉角度
    @required double angle,
    this.origin,
    this.alignment = Alignment.center,
    this.transformHitTests = true,
    Widget child,
  })
  
  // 建立一個平移矩陣
  Transform.translate({
    Key key,
    @required Offset offset,
    this.transformHitTests = true,
    Widget child,
  })
  
  // 建立一個縮放矩陣
  Transform.scale({
    Key key,
    // 設置縮放比例, 0-1的數值
    @required double scale,
    this.origin,
    this.alignment = Alignment.center,
    this.transformHitTests = true,
    Widget child,
  })
}
複製代碼

下面是每一種變換形式的具體示例

旋轉

Transform.rotate能夠對子widget進行旋轉變換, 以下代碼

Container(
  color: Colors.black,
  child: Transform.rotate(
    // 這裏☞旋轉的角度, math.pi是指180度
    angle: -math.pi / 4,
    child: Container(
      padding: const EdgeInsets.all(8.0),
      color: const Color(0xFFE8581C),
      child: const Text('https://titanjun.top'),
    ),
  )
)
複製代碼

image

平移

Transform.translate接收一個offset參數,能夠在繪製時沿x、y軸對子widget平移指定的距離

Container(
  color: Colors.black,
  child: Transform.translate(
    // 默認原點爲左上角,右移5像素,向下平移15像素 
    offset: const Offset(5.0, 15.0),
    child: Container(
      padding: const EdgeInsets.all(8.0),
      color: const Color(0xFF7F7F7F),
      child: const Text('Quarter'),
    ),
  )
)
複製代碼

image

縮放

Transform.scale能夠對子Widget進行縮小或放大

Container(
  color: Colors.black,
  child: Transform.scale(
    origin: Offset(5, 5),
    // 縮小爲原來的0.5倍
    scale: 0.5,
    child: Container(
      padding: const EdgeInsets.all(8.0),
      color: const Color(0xFFE8581C),
      child: const Text('Bad Ideas'),
    ),
  )
)
複製代碼

注意點

  • Transform的變換是應用在繪製階段,而並非應用在佈局(layout)階段
  • 因此不管對子widget應用何種變化,其佔用空間的大小和在屏幕上的位置都是固定不變的,由於這些是在佈局階段就肯定的
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration:BoxDecoration(color: Colors.red),
      child: Transform.scale(scale: 1.5,
          child: Text("Hello world")
      )
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
  ],
)
複製代碼

image

  • 因爲第一個Text應用變換(放大)後,其在繪製時會放大,但其佔用的空間依然爲紅色部分,因此第二個text會緊挨着紅色部分,最終就會出現文字有重合部分。
  • 因爲矩陣變化只會做用在繪製階段,因此在某些場景下,在UI須要變化時,能夠直接經過矩陣變化來達到視覺上的UI改變,而不須要去從新觸發build流程,這樣會節省layout的開銷,因此性能會比較好
  • 如以前介紹的Flow widget,它內部就是用矩陣變換來更新UI,除此以外,Flutter的動畫widget中也大量使用了Transform以提升性能

RotatedBox

  • RotatedBoxTransform.rotate功能類似,它們均可以對子widget進行旋轉變換,可是有一點不一樣:RotatedBox的變換是在layout階段,會影響在子widget的位置和大小
  • 咱們將上面介紹Transform.rotate時的示例改一下
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: <Widget>[
    DecoratedBox(
      decoration: BoxDecoration(color: Colors.red),
      //將Transform.rotate換成RotatedBox 
      child: RotatedBox(
        // int類型
        quarterTurns: 1, //旋轉90度(1/4圈)
        child: Text("Hello world"),
      ),
    ),
    Text("你好", style: TextStyle(color: Colors.green, fontSize: 18.0),)
  ],
),
複製代碼

image

因爲RotatedBox是做用於layout階段,因此widget會旋轉90度(而不僅是繪製的內容),decoration會做用到widget所佔用的實際空間上,因此就是上圖的效果。讀者能夠和前面Transform.rotate示例對比理解

Matrix4

一個4D變換矩陣, Transform使用Matrix4使其子Widget進行矩陣變換, 下面是其相關構造函數

// 4 x 4矩陣
factory Matrix4(double arg0, double arg1, double arg2, double arg3, double arg4, double arg5, double arg6, double arg7, double arg8, double arg9, double arg10, double arg11, double arg12, double arg13, double arg14, double arg15)

// 設置一個新的矩陣
factory Matrix4.columns(Vector4 arg0, Vector4 arg1, Vector4 arg2, Vector4 arg3)

// 複合平移、旋轉、縮放,造成新的轉換矩陣
factory Matrix4.compose(Vector3 translation, Quaternion rotation, Vector3 scale)

// 複製一個4*4的張量(矩陣)
factory Matrix4.copy(Matrix4 other)

// 縮放矩陣, Vector3(double x, double y, double z)
factory Matrix4.diagonal3(Vector3 scale)

// 縮放矩陣, 只是參數不一樣而已
factory Matrix4.diagonal3Values(double x, double y, double z)


Matrix4.fromBuffer(ByteBuffer buffer, int offset)

// 使用給定的Float64List構造Matrix4 
Matrix4.fromFloat64List(Float64List _m4storage)

// 將一個16位的一維數組轉換成4*4的矩陣
factory Matrix4.fromList(List<double> values)

// 恢復初始狀態,也就是4*4的單位矩陣
factory Matrix4.identity()

// 取相反的矩陣,就是反着來
factory Matrix4.inverted(Matrix4 other)

// 兩個4維向量的乘積合併
factory Matrix4.outer(Vector4 u, Vector4 v)

// 圍繞X軸旋轉
factory Matrix4.rotationX(double radians)

// 圍繞Y軸旋轉
factory Matrix4.rotationY(double radians)

// 圍繞Z軸旋轉
factory Matrix4.rotationZ(double radians)

// 扭曲變換
factory Matrix4.skew(double alpha, double beta)

// 沿着x軸扭曲
factory Matrix4.skewX(double alpha)

// 沿着y軸扭曲
factory Matrix4.skewY(double beta)

// 移動矩陣
factory Matrix4.translation(Vector3 translation)

// 移動矩陣, 參數不一樣而已
factory Matrix4.translationValues(double x, double y, double z)

// 全是0的4*4的張量
factory Matrix4.zero()
複製代碼

Container

  • Container是一個容器類widget,它自己不對應具體的RenderObject,它是DecoratedBoxConstrainedBoxTransformPaddingAlignwidget的一個組合widget
  • 因此咱們只需經過一個Container能夠實現同時須要裝飾、變換、限制的場景
  • 下面是Container的相關定義
Container({
    Key key,
    // 對其方式
    this.alignment,
    // 內邊距
    this.padding,
    // 背景顏色
    Color color,
    // 背景裝飾
    Decoration decoration,
    // 前景裝飾
    this.foregroundDecoration,
    double width,
    double height,
    //容器大小的限制條件
    BoxConstraints constraints,
    // 容器的外邊距, EdgeInsets
    this.margin,
    // 設置變換矩陣
    this.transform,
    this.child,
})
複製代碼
  • 容器的大小能夠經過widthheight屬性來指定,也能夠經過constraints來指定,若是同時存在時,widthheight優先。實際上Container內部會根據widthheight來生成一個constraints
  • colordecoration是互斥的,實際上,當指定color時,Container內會自動建立一個decoration

使用實例

經過使用來實現以下效果

image

Container(
  margin: EdgeInsets.only(top: 50.0, left: 120.0), //容器外補白
  constraints: BoxConstraints.tightFor(width: 200.0, height: 150.0), //卡片大小
  decoration: BoxDecoration(//背景裝飾
      gradient: RadialGradient( //背景徑向漸變
          colors: [Colors.red, Colors.orange],
          center: Alignment.topLeft,
          radius: .98
      ),
      boxShadow: [ //卡片陰影
        BoxShadow(
            color: Colors.black54,
            offset: Offset(2.0, 2.0),
            blurRadius: 4.0
        )
      ]
  ),
  transform: Matrix4.rotationZ(.2), //卡片傾斜變換
  alignment: Alignment.center, //卡片內文字居中
  child: Text( //卡片文字
    "5.20", style: TextStyle(color: Colors.white, fontSize: 40.0),
  ),
);
複製代碼

參考文獻


歡迎您掃一掃下面的微信公衆號,訂閱個人博客!

微信公衆號
相關文章
相關標籤/搜索