小菜在學習過程中,為了調整或适配 Widget 大小時,會設定 Widget 或嵌套使用一些限制 Widget;小菜針對性學習一下這一系列的限制 Box;
SizedBox
源碼分析
class SizedBox extends SingleChildRenderObjectWidget {
// 建立固定大小的限制Box
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);
// 建立父類允許最小尺寸的限制Box
const SizedBox.shrink({ Key key, Widget child })
: width = 0.0,
height = 0.0,
super(key: key, child: child);
// 建立指定大小的限制Box
SizedBox.fromSize({ Key key, Widget child, Size size })
: width = size?.width,
height = size?.height,
super(key: key, child: child);
}
分析源碼可知,SizeBox 繼承自 SingleChildRenderObjectWidget 僅提供子 Child 的存儲并不提供更新邏輯;且 SizedBox 提供了多種使用方法,小菜逐一嘗試;
案例嘗試
1. SizedBox({ Key key, this.width, this.height, Widget child })
SizedBox 可自定義 width 和 height,當限制寬高時,子 Widget 無論寬高如何,均預設填充;通過設定 double.infinity 填充父類 Widget 寬高,注意此時父類要有限制,不可是無限寬高;當 width 和 height 未設定時,根據子 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 是便捷方法,預設 width 和 height 均為 double.infinity,填充整個父類 Widget;
return SizedBox.expand(child: Container(color: Colors.blueAccent.withOpacity(0.4)));
3. SizedBox.shrink({ Key key, Widget child })
.shrink 同樣是便捷方法,但 width 和 height 均為 0.0,無論子 Widget 設定多少均不展示;小菜暫時未想出此類方法的應用場景;
return SizedBox.shrink(child: Container(color: Colors.pink.withOpacity(0.4)));
4. SizedBox.fromSize({ Key key, Widget child, Size size })
.fromSize 便捷方式與基本的建構方式基本相同,隻是 width 和 height 由 Size 封裝,小菜用此方法實作與基本方式相同的效果;
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 {
// 用指定的限制大小建立架構大小
const BoxConstraints({
this.minWidth = 0.0,
this.maxWidth = double.infinity,
this.minHeight = 0.0,
this.maxHeight = double.infinity,
});
// 僅用指定大小建立架構大小
BoxConstraints.tight(Size size)
: minWidth = size.width,
maxWidth = size.width,
minHeight = size.height,
maxHeight = size.height;
// 用指定的限制大小建立架構大小
const BoxConstraints.tightFor({
double width,
double height,
})
// 建立需要給定寬度或高度的框限制,除非它們是無限的
const BoxConstraints.tightForFinite({
double width = double.infinity,
double height = double.infinity,
})
// 建立禁止大小大于給定大小的框限制
BoxConstraints.loose(Size size)
: minWidth = 0.0,
maxWidth = size.width,
minHeight = 0.0,
maxHeight = size.height;
// 建立擴充為填充另一個框限制的框限制
const BoxConstraints.expand({
double width,
double height,
})
}
分析源碼可知,ConstrainedBox 同樣是繼承自 SingleChildRenderObjectWidget;限制方式主要是對 constraints 的操作;相對于 SizedBox 限制更為靈活;
1. BoxConstraints()
BoxConstraints 的構造方法可以設定最大最小寬度和高度四個屬性,在實際場景中可以靈活運用;其限制的大小按照 minWidth <= child.width <= maxWidth && minHeight <= child.Height <= maxHeight,當我們不設定寬高尺寸時,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 構造方法中需要傳一個固定尺寸的 Size 其中 minWidth == maxWidth == size.width && maxWidth == maxHeight == size.height;無論子 Widget 設定多大寬高均按照 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 方式的細化,可以自定義 width 和 height;若寬高未設定,則最大寬高為無限,最小寬高為 0.0;若設定寬高則以設定尺寸進行限制;
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 類似,預設最大寬高為無限,最小寬高為 0.0,其判斷的是設定寬高是否為無限,不是 double.infinity 則 minWidth == maxWidth == width && maxWidth == maxHeight == height 進行限制;
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 限制,實際展示與子 Widget 大小相關;
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 方式是填充方式,預設填滿父 Widget,若不設定寬高,預設 minWidth == maxWidth == double.infinity && minHeight == maxHeight == double.infinity,使用時注意父類限制;
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,所謂條條大路通羅馬,同一種效果可以有多種實作方式,但小菜認為還是應該多多了解,盡量嘗試最優方案;小菜對 Box 系列的研究還很淺顯,有錯誤的地方請多多指導!
來源: 阿策小和尚