- 原文地址:Flutter Layout Cheat Sheet
- 原文作者:Tomek Polański
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:EmilyQiRabbit
- 校對者:smilemuffie,suhanyujie
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/c778f35ed4724cb936adb14f874b45efa8c852fd6fde4dd00aab217b14c53069.png)
你需要了解 Flutter 的簡單佈局模版嗎? 現在我將展示給你我總結的一系列 Flutter 佈局程式碼片段。我會盡量保證程式碼簡短易懂,並且會給出效果圖。 但是我們仍舊需要循序漸進 —— 模版目錄將會隨之逐步深入。我將會將更多的篇幅集中於 Flutter 部件的應用,而不是單純陳列元件(Flutter Gallery 在這一點做的很好!) 如果你對於 Flutter 佈局還有其他疑問,或者想要分享你的程式碼,請留言給我!
目錄
- Row 和 Column
- IntrinsicWidth 和 IntrinsicHeight
- Stack
- Expanded
- ConstrainedBox
- Container
- 裝飾(decoration):BoxDecoration
- 圖片(image):DecorationImage
- 邊框(border):Border
- 邊框半徑(borderRadius):BorderRadius
- 形狀(shape):BoxShape
- 陰影(boxShadow):
List<BoxShadow>
- 漸變(gradient):RadialGradient
- 背景混合模式(backgroundBlendMode):BlendMode
- SizedBox
- SafeArea
Row 和 Column
MainAxisAlignment
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/5d9866522b80e67ecebbde1a9a437ab319d78421e39e9b1026a96d1275191146.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/975927b9879ccd20cd683ccd671409cc37f0e01b6f3c750310bc6b68d9a633aa.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/507de55008fce9e17aa3c60617ed620a5f8f061596f9b1a95b1f4ee9630d4542.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a71962bef9ff6c16a624e8830519fc06f64622c684052d707a375c7d2fe835d1.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/e16a1024047b4a8995a665c16c224d446721bcde91ed08e0274098aa501012a2.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/e9ed8fa63154ed5316e56fe25ff9f8455e69f9f48c8e8f7a312aa5ff94d37e44.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/eaa4413e3a2636b3cd1eee8e3044d68c5500a0bb3fb0bda8147822e503d228ce.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/464ad1fd5985f7450894a300bf6fb708c929bfb2629c8fc6b453333fb4b5988e.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/f91f0fd86b46fd79c13fffe29745b5f899ba2eac9c081902d67292e25473c4a5.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/39ed766eea0a0ec5d5075a8e65f15942c84342307d07e5bace6ee3d80e405c9e.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/6e0c7ee457ed3f553a442cdfdc5e711360370c27417a306a307d28727167a608.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/f407b04fb25c578c6ed842977cd459887073cccb1ce1d6e752f3ad32cfba11a3.png)
Row /*或 Column*/(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/47daffb3e6e25f38a7e27cef3cbc244df903ca0a5cd0ecd91c2f68e03a6e849a.png)
如果你想要不同字元的基線對齊,你應該使用 CrossAxisAlignment.baseline
。
Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
'Baseline',
style: Theme.of(context).textTheme.display3,
),
Text(
'Baseline',
style: Theme.of(context).textTheme.body1,
),
],
),
複製程式碼
CrossAxisAlignment
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/11a6e9fdfe0fd5f2d74c946460f0e689f716f93397a25a8645c386a66bede00f.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/d0de71080ad82caf3888892d41190306a2da07ca86efb3c55a3fa844a8a08fa6.png)
Row /*或 Column*/(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/fe9daac9dca5e3a291fdfa69ea820de9da2f4aad10813e09a226d310a945e36a.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/7adaf6de23cbc2747688cc1da5ac220fe874db79ad26e68e704546fc68b5fd1d.png)
Row /*或 Column*/(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/c1e4943f1ed9bf4beaee14d28b570b34edc42856b26a9e74dcda63414977d76b.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/e7045881f60f8bd44d28d2fec5a7341e32ed0cafe85ecd5b0f2bca8912dad118.png)
Row /*或 Column*/(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/b2aaf8e998ae56aa5d00d4a7ae718c1442679a13e73d357f491b36e2e57770e6.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/0ebe55cc48011d4fdb9e29c1a2fddc24dea72962be281e69d544a3664072bfb3.png)
Row /*或 Column*/(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),
複製程式碼
MainAxisSize
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/5051ce344e9fc9c504c139650f57bd985575af2c7dd53387b028a3fab4a105bf.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a34e50aafae1d55df99528380553808f35318f119e2cea33266db8887949a2f2.png)
Row /*或 Column*/(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a2f82ffa39acc621fde48a4aec84fe07e97036eea915aca632a190a5d8244b3c.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/fb46fa3af15f629235be98f811c0db232368c93b6ddb5ee8daf51ff146ecbdf6.png)
Row /*或 Column*/(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
IntrinsicWidth 和 IntrinsicHeight
想要某行或列中所有部件和最高/最寬的部件一樣高/寬?不要亂找了,答案在這裡!
當你有這種樣式的佈局:
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/3399db9010e7dff5a0a3ca46d0b55c00ac19bcade75b352c254652610fd1040f.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('IntrinsicWidth')),
body: Center(
child: Column(
children: <Widget>[
RaisedButton(
onPressed: () {},
child: Text('Short'),
),
RaisedButton(
onPressed: () {},
child: Text('A bit Longer'),
),
RaisedButton(
onPressed: () {},
child: Text('The Longest text button'),
),
],
),
),
);
}
複製程式碼
但是你希望所有的按鈕都和最寬的按鈕等寬,只需要使用 IntrinsicWidth
:
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/b55532bd5066daf4231facc13562357d0fb484cfa59d2f990f7c8d8557bd9bc2.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('IntrinsicWidth')),
body: Center(
child: IntrinsicWidth(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
RaisedButton(
onPressed: () {},
child: Text('Short'),
),
RaisedButton(
onPressed: () {},
child: Text('A bit Longer'),
),
RaisedButton(
onPressed: () {},
child: Text('The Longest text button'),
),
],
),
),
),
);
}
複製程式碼
如果你需要的是讓所有部件和最高的部件等高,可以結合使用 IntrinsicHeight
和 Row
部件。
Stack
非常適用於將部件疊加在一起
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/d5abf16a245e3cdae347de5f11ba232b997c77265cc160afa17ba99fc8532f46.png)
@override
Widget build(BuildContext context) {
Widget main = Scaffold(
appBar: AppBar(title: Text('Stack')),
);
return Stack(
fit: StackFit.expand,
children: <Widget>[
main,
Banner(
message: "Top Start",
location: BannerLocation.topStart,
),
Banner(
message: "Top End",
location: BannerLocation.topEnd,
),
Banner(
message: "Bottom Start",
location: BannerLocation.bottomStart,
),
Banner(
message: "Bottom End",
location: BannerLocation.bottomEnd,
),
],
);
}
複製程式碼
如果想使用自己的部件,需要將它們放置在 Positioned
裡面
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/8fbc9d7d64615c65ca5a7320db3556af0976ffb4cbe1af541ba49d6c3e5fb162.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Stack')),
body: Stack(
fit: StackFit.expand,
children: <Widget>[
Material(color: Colors.yellowAccent),
Positioned(
top: 0,
left: 0,
child: Icon(Icons.star, size: 50),
),
Positioned(
top: 340,
left: 250,
child: Icon(Icons.call, size: 50),
),
],
),
);
}
複製程式碼
如果你不想去猜測 top 或 bottom 的值,你可以使用 LayoutBuilder
來檢索它們
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/df7b2e94c8b54bc460528fcbe9ed40e4d9d6bd2e3bcd34ec18bfebcb68823234.png)
Widget build(BuildContext context) {
const iconSize = 50;
return Scaffold(
appBar: AppBar(title: Text('Stack with LayoutBuilder')),
body: LayoutBuilder(
builder: (context, constraints) =>
Stack(
fit: StackFit.expand,
children: <Widget>[
Material(color: Colors.yellowAccent),
Positioned(
top: 0,
child: Icon(Icons.star, size: iconSize),
),
Positioned(
top: constraints.maxHeight - iconSize,
left: constraints.maxWidth - iconSize,
child: Icon(Icons.call, size: iconSize),
),
],
),
),
);
}
複製程式碼
Expanded
Expanded
可以和 Flex\Flexbox 佈局一起應用,並且非常適用於分配多元素的空間。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/72c7ffde729cd2dd463b867a87145dc2b8222eb8f143c5ef5b8ca888bd424091.png)
Row(
children: <Widget>[
Expanded(
child: Container(
decoration: const BoxDecoration(color: Colors.red),
),
flex: 3,
),
Expanded(
child: Container(
decoration: const BoxDecoration(color: Colors.green),
),
flex: 2,
),
Expanded(
child: Container(
decoration: const BoxDecoration(color: Colors.blue),
),
flex: 1,
),
],
),
複製程式碼
ConstrainedBox
預設情況下,大多陣列件都會使用盡可能小的空間:
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/00e2f1e8e29649322bd04c6f55b6e969dab498db74c6e71f80b424b48b8c30c4.png)
Card(child: const Text('Hello World!'), color: Colors.yellow)
複製程式碼
ConstrainedBox
讓部件可以使用期望的剩餘空間。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/c274cbd0694a65a7b4045ef69dc22438253ee16bac852001fde1ce3772a88f51.png)
ConstrainedBox(
constraints: BoxConstraints.expand(),
child: const Card(
child: const Text('Hello World!'),
color: Colors.yellow,
),
),
複製程式碼
你可以使用 BoxConstraints
指定部件可以使用多大的空間 —— 通過指定 height
/width
的 min
/max
屬性。
BoxConstraints.expand
將會讓元件使用無限制(所有可用)的空間,除非另有指定:
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a39f853559228e761209ee53b1196fb6b605f7cbebcb27f9870b169158a9d225.png)
ConstrainedBox(
constraints: BoxConstraints.expand(height: 300),
child: const Card(
child: const Text('Hello World!'),
color: Colors.yellow,
),
),
複製程式碼
上面程式碼和如下程式碼等效:
ConstrainedBox(
constraints: BoxConstraints(
minWidth: double.infinity,
maxWidth: double.infinity,
minHeight: 300,
maxHeight: 300,
),
child: const Card(
child: const Text('Hello World!'),
color: Colors.yellow,
),
),
複製程式碼
Container
最常用的部件之一 —— 並且它之所以這麼常用是有原因的:
用於佈局工具的 Container
如果你沒有指定 Container
的 height
和 width
,它將和 child
的大小相同
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/5b16ae97a0ce4598f1be238e8d4cfc7d3cc832edcca45ad7c5632f488eedc87a.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Container as a layout')),
body: Container(
color: Colors.yellowAccent,
child: Text("Hi"),
),
);
}
複製程式碼
如果你想要 Container
擴大到和它的父級元素相等,對 height
和 width
屬性使用 double.infinity
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/990504ed6514d16fea4424615c84a6333446d07b41f520e45c7c7c4813844c5f.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Container as a layout')),
body: Container(
height: double.infinity,
width: double.infinity,
color: Colors.yellowAccent,
child: Text("Hi"),
),
);
}
複製程式碼
Container 的裝飾
你可以使用 color 屬性來改變 Container
的背景色,但是 decoration
和 foregroundDecoration
則可以做更多。(使用這兩個屬性,你可以徹底改變 Container
的外觀,這部分我將在後續討論,因為這部分內容很多)
decoration
總會放置在 child 後面,而 foregroundDecoration
則在 child
的上面。

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Container.decoration')),
body: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(color: Colors.yellowAccent),
child: Text("Hi"),
),
);
}
複製程式碼

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Container.foregroundDecoration')),
body: Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(color: Colors.yellowAccent),
foregroundDecoration: BoxDecoration(color: Colors.red.withOpacity(0.5)),
child: Text("Hi"),
),
);
}
複製程式碼
Container 的變換
如果你不想使用 Transform
部件來改變你的佈局,你可以使用 Container
的 transform
屬性
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/1c10e88d90ba681ea7f406344b72e5d4693aaa0c568c59af8c4d025e8ebc6e2b.png)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Container.transform')),
body: Container(
height: 300,
width: 300,
transform: Matrix4.rotationZ(pi / 4),
decoration: BoxDecoration(color: Colors.yellowAccent),
child: Text(
"Hi",
textAlign: TextAlign.center,
),
),
);
}
複製程式碼
BoxDecoration
裝飾效果通常用於容器元件,來改變元件的外觀。
圖片(image):DecorationImage
將圖片作為背景:
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/37023cce7f30bbc15eeabcf927ac152e0efed994acba89c77b8ca9cd74fca36e.png)
Scaffold(
appBar: AppBar(title: Text('image: DecorationImage')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.yellow,
image: DecorationImage(
fit: BoxFit.fitWidth,
image: NetworkImage(
'https://flutter.io/images/catalog-widget-placeholder.png',
),
),
),
),
),
);
複製程式碼
邊框(border):Border
指定容器的邊框樣式。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/faa4f83120ba37c07f7cc60d1c83317e78e829adca49500cd45b2c690b6ae1ec.png)
Scaffold(
appBar: AppBar(title: Text('border: Border')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.yellow,
border: Border.all(color: Colors.black, width: 3),
),
),
),
);
複製程式碼
邊框半徑(borderRadius):BorderRadius
讓邊框可以是圓角。
如果裝飾的 shape
是 BoxShape.circle
,那麼 borderRadius
將無效
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/50094f41b0abf9ce1f1359a5015c12159d519c55759d945c87601ed35e945170.png)
Scaffold(
appBar: AppBar(title: Text('borderRadius: BorderRadius')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.yellow,
border: Border.all(color: Colors.black, width: 3),
borderRadius: BorderRadius.all(Radius.circular(18))),
),
),
);
複製程式碼
形狀(shape):BoxShape
盒子的形狀可以是長方形、正方形、橢圓或者圓形。
對於其他任意形狀,你應該使用 ShapeDecoration
而不是 BoxDecoration
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/1729fee7ef336a27c9e89d6304046f5ec36224f21f8c1ce1df3f0d319486e6ab.png)
Scaffold(
appBar: AppBar(title: Text('shape: BoxShape')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.yellow,
shape: BoxShape.circle,
),
),
),
);
複製程式碼
陰影(boxShadow):List<BoxShadow>
可以給容器新增陰影。
這個引數是一個列表,這樣你就可以定義多種不同的陰影,然後將它們組合在一起。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/c916c5a522a195eab4f0259ee37bbe324027393860b19c1667a6c9ae011dcb51.png)
Scaffold(
appBar: AppBar(title: Text('boxShadow: List<BoxShadow>')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
color: Colors.yellow,
boxShadow: const [
BoxShadow(blurRadius: 10),
],
),
),
),
);
複製程式碼
漸變(gradient)
有三種型別的漸變:LinearGradient
、RadialGradient
和 SweepGradient
。

Scaffold(
appBar: AppBar(title: Text('gradient: LinearGradient')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: const [
Colors.red,
Colors.blue,
],
),
),
),
),
);
複製程式碼

Scaffold(
appBar: AppBar(title: Text('gradient: RadialGradient')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
gradient: RadialGradient(
colors: const [Colors.yellow, Colors.blue],
stops: const [0.4, 1.0],
),
),
),
),
);
複製程式碼

Scaffold(
appBar: AppBar(title: Text('gradient: SweepGradient')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
gradient: SweepGradient(
colors: const [
Colors.blue,
Colors.green,
Colors.yellow,
Colors.red,
Colors.blue,
],
stops: const [0.0, 0.25, 0.5, 0.75, 1.0],
),
),
),
),
);
複製程式碼
背景混合模式(backgroundBlendMode)
backgroundBlendMode
是 BoxDecoration
中最複雜的屬性。
它可以混合 BoxDecoration
的顏色和漸變,並且無論 BoxDecoration
在何種元素之上。
有了 backgroundBlendMode
,你可以使用 BlendMode
列舉型別中的一長串演算法。
首先,配置 BoxDecoration
為 foregroundDecoration
,它被渲染於 Container
子元素的上方(而 decoration
被渲染於子元素的後面)。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/27d1c8621fbfc17b16b2b85378963615b526ac008a656081d8d4aa5730d97be1.png)
Scaffold(
appBar: AppBar(title: Text('backgroundBlendMode')),
body: Center(
child: Container(
height: 200,
width: 200,
foregroundDecoration: BoxDecoration(
backgroundBlendMode: BlendMode.exclusion,
gradient: LinearGradient(
colors: const [
Colors.red,
Colors.blue,
],
),
),
child: Image.network(
'https://flutter.io/images/catalog-widget-placeholder.png',
),
),
),
);
複製程式碼
backgroundBlendMode
不僅影響它所在的 Container
。
backgroundBlendMode
能改變從 Container
的部件樹中任意部件的顏色。
下面這段程式碼中,有一個作為父級元素的 Container
,它渲染了一張圖片 image
和一個使用了 backgroundBlendMode
的子元素 Container
。你仍舊會得到和前一段程式碼相同的效果。
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a3cef994c5284534ccf18ce9921de682f76353304d7324be7ab02e0e4673cf4c.png)
Scaffold(
appBar: AppBar(title: Text('backgroundBlendMode')),
body: Center(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://flutter.io/images/catalog-widget-placeholder.png',
),
),
),
child: Container(
height: 200,
width: 200,
foregroundDecoration: BoxDecoration(
backgroundBlendMode: BlendMode.exclusion,
gradient: LinearGradient(
colors: const [
Colors.red,
Colors.blue,
],
),
),
),
),
),
);
複製程式碼
SizedBox
這是最簡單但是最有用的部件
用作 ConstrainedBox 的 SizedBox
SizedBox
可以實現和 ConstrainedBox
相似的效果
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/f3d51eaf6c7754a758b1fa3574341fa5fe596d14fb245ae9563b563f3ec912bc.png)
SizedBox.expand(
child: Card(
child: Text('Hello World!'),
color: Colors.yellowAccent,
),
),
複製程式碼
用作內邊距的 SizedBox
如果你需要新增內邊距或者外邊距,你可以選擇 Padding
或者 Container
部件。但是它們都不如新增 Sizedbox
簡單易讀
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/4ef5bdb678e37300c32915fc1766771429ce487de792869f7af8a7265ffcfe93.png)
Column(
children: <Widget>[
Icon(Icons.star, size: 50),
const SizedBox(height: 100),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),
複製程式碼
用作不可見物件的 SizedBox
很多時候你希望通過一個布林值(bool
)來控制元件的顯示和隱藏
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/8d468955eb87e5f3b07355ce8641367d9cb8bd9a446a48a463fd7d6b5f7059f0.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/9e8066446f4d18a9c9005fccaa9e7b6a4c2e2bb6dbcf87a54176af35cd6f02b3.png)
Widget build(BuildContext context) {
bool isVisible = ...
return Scaffold(
appBar: AppBar(
title: Text('isVisible = $isVisible'),
),
body: isVisible
? Icon(Icons.star, size: 150)
: const SizedBox(),
);
}
複製程式碼
由於 SizedBox
有一個 const
建構函式,使用 const SizedBox()
就變得非常簡單。
更簡單的解決方案是使用 Opacity
部件,然後將 opacity
的值改成 0.0
。這個方案的缺點是雖然元件不可見,但是它依舊佔據空間。
SafeArea
在不同的平臺上,有很多特殊的位置,比如 Android 系統的狀態列,或者 iPhone X 的“齊劉海”,我們應該避免在這些位置放置元素。
解決方案就是使用 SafeArea
部件(下面的例子分別是使用和沒使用 SafeArea
的效果)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/ff31b17e42784d256902b65189c23b766b6c5165beb26372dbb011767fa8ae50.png)
![[譯] Flutter 佈局備忘錄](https://i.iter01.com/images/a795d97a21fe0eaf5067791564004e810b0dc42428ab095d8c58950b1ec9fe84.png)
Widget build(BuildContext context) {
return Material(
color: Colors.blue,
child: SafeArea(
child: SizedBox.expand(
child: Card(color: Colors.yellowAccent),
),
),
);
}
複製程式碼
更多內容敬請期待
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。