Flutter 66: 圖解基本約束 Box (一)

??????小菜在學(xué)習(xí)過程中,為了調(diào)整或適配 Widget 大小時(shí),會(huì)設(shè)置 Widget 或嵌套使用一些約束 Widget;小菜針對性學(xué)習(xí)一下這一系列的約束 Box

SizedBox

源碼分析

class SizedBox extends SingleChildRenderObjectWidget {
  // 創(chuàng)建固定大小的約束Box
  const SizedBox({ Key key, this.width, this.height, Widget child })
    : super(key: key, child: child);

  // 創(chuàng)建父類允許最大尺寸的約束Box
  const SizedBox.expand({ Key key, Widget child })
    : width = double.infinity,
      height = double.infinity,
      super(key: key, child: child);

  // 創(chuàng)建父類允許最小尺寸的約束Box
  const SizedBox.shrink({ Key key, Widget child })
    : width = 0.0,
      height = 0.0,
      super(key: key, child: child);

  // 創(chuàng)建指定大小的約束Box
  SizedBox.fromSize({ Key key, Widget child, Size size })
    : width = size?.width,
      height = size?.height,
      super(key: key, child: child);
}

??????分析源碼可知,SizeBox 繼承自 SingleChildRenderObjectWidget 僅提供子 Child 的存儲(chǔ)并不提供更新邏輯;且 SizedBox 提供了多種使用方法,小菜逐一嘗試;

案例嘗試

1. SizedBox({ Key key, this.width, this.height, Widget child })

??????SizedBox 可自定義 widthheight,當(dāng)限制寬高時(shí),子 Widget 無論寬高如何,均默認(rèn)填充;通過設(shè)置 double.infinity 填充父類 Widget 寬高,注意此時(shí)父類要有限制,不可是無限寬高;當(dāng) widthheight 未設(shè)置時(shí),根據(jù)子 Widget 大小展示;

return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.teal.withOpacity(0.4)));
return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.red.withOpacity(0.4), width: 200.0, height: 200.0));
return SizedBox(width: 100.0, height: 100.0, child: Container(color: Colors.pink.withOpacity(0.4), width: 50.0, height: 50.0));
return SizedBox(width: double.infinity, height: 100.0, child: Container(color: Colors.blueAccent.withOpacity(0.4)));
2. SizedBox.expand({ Key key, Widget child })

??????.expand 是便捷方法,默認(rèn) widthheight 均為 double.infinity,填充整個(gè)父類 Widget

return SizedBox.expand(child: Container(color: Colors.blueAccent.withOpacity(0.4)));
3. SizedBox.shrink({ Key key, Widget child })

??????.shrink 同樣是便捷方法,但 widthheight 均為 0.0,無論子 Widget 設(shè)置多少均不展示;小菜暫時(shí)未想出此類方法的應(yīng)用場景;

return SizedBox.shrink(child: Container(color: Colors.pink.withOpacity(0.4)));
4. SizedBox.fromSize({ Key key, Widget child, Size size })

??????.fromSize 便捷方式與基本的構(gòu)建方式基本相同,只是 widthheightSize 封裝,小菜用此方法實(shí)現(xiàn)與基本方式相同的效果;

return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.teal.withOpacity(0.4)));
return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.red.withOpacity(0.4), width: 200.0, height: 200.0));
return SizedBox.fromSize(size: Size(100.0, 100.0), child: Container(color: Colors.pink.withOpacity(0.4), width: 50.0, height: 50.0));
return SizedBox.fromSize(size: Size(double.infinity, 100.0), child: Container(color: Colors.blueAccent.withOpacity(0.4)));

ConstrainedBox

源碼分析

class ConstrainedBox extends SingleChildRenderObjectWidget {
  ConstrainedBox({
    Key key,
    @required this.constraints,
    Widget child,
  })
}

class BoxConstraints extends Constraints {
  // 用指定的約束大小創(chuàng)建框架大小
  const BoxConstraints({
    this.minWidth = 0.0,
    this.maxWidth = double.infinity,
    this.minHeight = 0.0,
    this.maxHeight = double.infinity,
  });

  // 僅用指定大小創(chuàng)建框架大小
  BoxConstraints.tight(Size size)
    : minWidth = size.width,
      maxWidth = size.width,
      minHeight = size.height,
      maxHeight = size.height;

  // 用指定的約束大小創(chuàng)建框架大小
  const BoxConstraints.tightFor({
    double width,
    double height,
  })

  // 創(chuàng)建需要給定寬度或高度的框約束,除非它們是無限的
  const BoxConstraints.tightForFinite({
    double width = double.infinity,
    double height = double.infinity,
  })

  // 創(chuàng)建禁止大小大于給定大小的框約束
  BoxConstraints.loose(Size size)
    : minWidth = 0.0,
      maxWidth = size.width,
      minHeight = 0.0,
      maxHeight = size.height;

  // 創(chuàng)建擴(kuò)展為填充另一個(gè)框約束的框約束
  const BoxConstraints.expand({
    double width,
    double height,
  })
}

??????分析源碼可知,ConstrainedBox 同樣是繼承自 SingleChildRenderObjectWidget;約束方式主要是對 constraints 的操作;相對于 SizedBox 約束更為靈活;

案例嘗試

1. BoxConstraints()

??????BoxConstraints 的構(gòu)造方法可以設(shè)置最大最小寬度和高度四個(gè)屬性,在實(shí)際場景中可以靈活運(yùn)用;其約束的大小按照 minWidth <= child.width <= maxWidth && minHeight <= child.Height <= maxHeight,當(dāng)我們不設(shè)置寬高尺寸時(shí),minWidth = 0.0 && minHeight = 0.0 && maxWidth = double.infinity && maxHeight = double.infinity;

return ConstrainedBox(constraints: BoxConstraints(), child: Container(color: Colors.pink.withOpacity(0.4), child: _textWid('ConstrainedBox')));
return ConstrainedBox(constraints: BoxConstraints(), child: Container(color: Colors.blueAccent.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints(minWidth: 100.0, minHeight: 100.0), child: Container(color: Colors.orange.withOpacity(0.4), child: _textWid('ConstrainedBox')));
return ConstrainedBox(constraints: BoxConstraints(maxHeight: 100.0, maxWidth: 100.0),  child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
2. BoxConstraints.tight(Size size)

??????.tight 構(gòu)造方法中需要傳一個(gè)固定尺寸的 Size 其中 minWidth == maxWidth == size.width && maxWidth == maxHeight == size.height;無論子 Widget 設(shè)置多大寬高均按照 Size 寬高約束;

return ConstrainedBox(constraints: BoxConstraints.tight(Size(110.0, 120.0)),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
3. BoxConstraints.tightFor()

??????小菜理解 .tightFor 方式是 .tight 方式的細(xì)化,可以自定義 widthheight;若寬高未設(shè)置,則最大寬高為無限,最小寬高為 0.0;若設(shè)置寬高則以設(shè)置尺寸進(jìn)行約束;

return ConstrainedBox(constraints: BoxConstraints.tightFor(height: 110.0),
        child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.tightFor(width: 110.0, height: 120.0),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
4. BoxConstraints.tightForFinite()

??????.tightForFinite.tightFor 類似,默認(rèn)最大寬高為無限,最小寬高為 0.0,其判斷的是設(shè)置寬高是否為無限,不是 double.infinityminWidth == maxWidth == width && maxWidth == maxHeight == height 進(jìn)行約束;

return ConstrainedBox(constraints: BoxConstraints.tightForFinite(),
        child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.tightForFinite(width: 110.0, height: 120.0),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
5. BoxConstraints.loose()

??????.loose 方式限制給定 Size 大小,minWidth / minHeight 均為 0.0,最大寬高為 Size 大小;其中整體約束由 Size 限制,實(shí)際展示與子 Widget 大小相關(guān);

return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 150.0)),
        child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 150.0)),
        child: Container(width: 200.0, height: 200.0, color: Colors.grey.withOpacity(0.6),
            child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.loose(Size(110.0, 120.0)),
        child: Container(width: 100.0, height: 100.0, color: Colors.green.withOpacity(0.6),
            child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
6. BoxConstraints.expand()

??????大部分 .expand 方式是填充方式,默認(rèn)填滿父 Widget,若不設(shè)置寬高,默認(rèn) minWidth == maxWidth == double.infinity && minHeight == maxHeight == double.infinity,使用時(shí)注意父類約束;

return ConstrainedBox(constraints: BoxConstraints.expand(),
    child: Container(color: Colors.teal.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));
return ConstrainedBox(constraints: BoxConstraints.expand(width: 110.0, height: 150.0),
    child: Container(color: Colors.purple.withOpacity(0.4), child: _textWid('ConstrainedBox: A widget that imposes additional constraints on its child.')));

??????Flutter 提供了多種約束 Box,所謂條條大路通羅馬,同一種效果可以有多種實(shí)現(xiàn)方式,但小菜認(rèn)為還是應(yīng)該多多了解,盡量嘗試最優(yōu)方案;小菜對 Box 系列的研究還很淺顯,有錯(cuò)誤的地方請多多指導(dǎo)!

來源: 阿策小和尚

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容