0
点赞
收藏
分享

微信扫一扫

Flutter 布局备忘录 -- 多图警告,干货建议收藏

你是否需要了解 ​​Flutter​​ 布局的案例?

这里我将展示我在使用 ​​Flutter​​ 布局的代码片段。我将通过精美的代码片段结合可视化的图形来举例。

本文注重 ​​Flutter​​ 部件中比较有用的一些来展示,而不是走马观花展示一大推的部件内容。

本文是翻译的文章,采用意译的方式

Row and Column

行(Row)和列(Column)的布局

MainAxisAlignment

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_02

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_03

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_04

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_05

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_06

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_07

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_08

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_09

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_10

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_11

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_12

Row /*or Column*/(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

CrossAxisAlignment

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_13

如果你需要文本是针对基线对齐,那么你应该使用 ​​CrossAxisAlignment.baseline​​。

Row(
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
'Baseline',
style: Theme.of(context).textTheme.headline2,
),
Text(
'Baseline',
style: Theme.of(context).textTheme.bodyText2,
),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_14

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_15

Row /*or Column*/(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_16

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_17

Row /*or Column*/(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_18

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_19

Row /*or Column*/(
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_20

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_21

Row /*or Column*/(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 200),
Icon(Icons.star, size: 50),
],
),

MainAxisSize

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_22

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_23

Row /*or Column*/(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

Row

Column

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_24

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_25

Row /*or Column*/(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

IntrinsicWidth and IntrinsicHeight

在行列布局中,如何使得所有的部件跟宽度/高度最大的部件同宽/同高呢?如下:

我们假有下面的布局:

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_26

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​​:

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

​Stack​​ 很适合小部件相互叠加。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_27

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 布局备忘录 -- 多图警告,干货建议收藏_iOS_28

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),
),
],
),
);
}

如果你不想猜测顶部/底部的值,你可以使用 ​​LayoutBuilder​​ 部件来检索它们的值。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_29

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 布局备忘录 -- 多图警告,干货建议收藏_iOS_30

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 布局备忘录 -- 多图警告,干货建议收藏_ico_31

Card(
child: const Text('Hello World!'),
color: Colors.yellow,
),

​ConstrainedBox​​ 允许小部件根据需要使用剩下的空间。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_32

ConstrainedBox(
constraints: BoxConstraints.expand(),
child: const Card(
child: const Text('Hello World!'),
color: Colors.yellow,
),
),

使用 ​​BoxConstraints​​,你可以指定一个小部件可以有多少空间,你可以指定高度/宽度的最小/最大值。

除非指定值,否则 ​​BoxConstraints.expand​​ 使用无限的空间量(也就是使用剩下的所有空间):

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_33

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,
),
),

Align

有时候,我们很难设置我们的小部件到正确的大小 -- 比如,它们自由伸展,但是这不是你想要的。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_34

当你在 ​​Column​​​ 中使用 ​​CrossAxisAlignment.stretch​​ 的时候,上面的现象就会发生,而你想要的是这个按钮不伸展。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_35

Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Align(
child: RaisedButton(
onPressed: () {},
child: const Text('Button'),
),
),
],
),

当你的小部件并不受限你设定的约束时,那么你可以尝试使用 ​​Align​​ 部件包裹它。

Container

​Container​​ 是最常用的部件之一 -- 有如下的好处:

Container as a layout tool

当你没有指定 ​​Container​​​ 的高度 ​​height​​​ 或者宽度 ​​width​​​ 的时候,它会自动适配 ​​child​​ 子部件的大小。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_36

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 布局备忘录 -- 多图警告,干货建议收藏_iOS_37

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 as decoration

你可以使用 ​​Container​​​ 的 ​​color​​​ 属性来更改其背景颜色,但是你也可以使用 ​​decoration​​​ 和 ​​foregroundDecoration​​​ 来更改。(使用这两个属性,你完全可以更改 ​​Container​​ 的样子,这个我们迟点说)。

​decoration​​​ 总是在 ​​child​​​ 属性的后面,而 ​​foregroundDecoration​​​ 总是在 ​​child​​ 属性的后面。(这也不一定)

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_38

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"),
),
);
}

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_39

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 as Transform

如果你不想使用 ​​Transform​​​ 部件来更改布局,你可以直接使用 ​​Container​​​ 中的 ​​transform​​ 属性。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_40

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

​decoration​​​ 通常用于更改 ​​Container​​ 部件的外观。

image: DecorationImage

图片作为背景:

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_41

Widget build(BuildContext context) {
return 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.dev/images/catalog-widget-placeholder.png', // 地址已经无效

border: Border

指定 ​​Container​​ 的边框看起来该怎样。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_42

Widget build(BuildContext context) {
return 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 布局备忘录 -- 多图警告,干货建议收藏_iOS_43

Widget build(BuildContext context) {
return 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

​BoxDecoration​​ 可以是矩形/正方形或者椭圆/圆形。

对于其他形状,你可以使用 ​​ShapeDecoration​​​ 代替 ​​BoxDecoration​​。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_44

Widget build(BuildContext context) {
return 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

为 ​​Container​​ 添加阴影。

这个参数是一个列表,你可以指定多个不同的阴影并将它们合并在一起。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_45

Widget build(BuildContext context) {
return 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​​。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_46

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('gradient: LinearGradient')),
body: Center(
child: Container(
height: 200,
width: 200,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: const

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_47

Widget build(BuildContext context) {
return 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],
),
),
),
),
);
}

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_48

Widget build(BuildContext context) {
return 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 布局备忘录 -- 多图警告,干货建议收藏_iOS_49

Widget build(BuildContext context) {
return 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', // 图片 404

​backgroundBlendMode​​​ 不仅仅影响它所在的 ​​Container​​。

​backgroundBlendMode​​​ 改变其所在 ​​Container​​ 及其一下部件树的内容的颜色。

下面的代码又一个父部件 ​​Container​​​ 来绘制一个 ​​image​​​,然后有一个子部件 ​​Container​​​ 来使用 ​​backgroundBlendMode​​,但是你还是获取到和之前的效果。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_50

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('backgroundBlendMode')),
body: Center(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: NetworkImage(
'https://flutter.io/images/catalog-widget-placeholder.png', // 404
),
),
),
child: Container(
height: 200,
width: 200,
foregroundDecoration: BoxDecoration(
backgroundBlendMode: BlendMode.exclusion,
gradient: LinearGradient(
colors: const

Material

有切角的边框。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_51

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('shape: BeveledRectangleBorder')),
body: Center(
child: Material(
shape: const BeveledRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
side: BorderSide(color: Colors.black, width: 4),
),
color: Colors.yellow,
child: Container(
height: 200,
width: 200,
),
),
),
);
}

Slivers

SliverFillRemaining

即便没有足够的空间,当你想要将内容居中,这个部件也是不可替代的。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_52

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('SliverFillRemaining')),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
FlutterLogo(size: 200),
Text(
'This is some longest text that should be centered'
'together with the logo',
textAlign: TextAlign.center,
),
],
),
),
],
),
);
}

如果居中的内容没有足够的空间,​​SliverFillRemaining​​ 将变为可滚动。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_53

如果没使用 ​​SliverFillRemaining​​,内容将会像下面这样溢出:

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_54

Filling the remaining space

除了对内容居中有用之外,​​SliverFillRemaining​​​ 还会填充剩余视口的可用空间。为此,此部件必须放置在 ​​CustomScrollView​​​ 中,并且必须是最后一个 ​​sliver​​。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_55

如果没有足够的空间,部件将变为可滚动。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_前端_56

Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('SliverFillRemaining')),
body: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate(const [
ListTile(title: Text('First item')),
ListTile(title: Text('Second item')),
ListTile(title: Text('Third item')),
ListTile(title: Text('Fourth item')),
]),
),
SliverFillRemaining(
hasScrollBody: false,
child: Container(
color: Colors.yellowAccent,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
FlutterLogo(size: 200),
Text(
'This is some longest text that should be centered'
'together with the logo',
textAlign: TextAlign.center,
),
],
),
),
),
],
),
);
}

SizedBox

​SizedBox​​ 是最简单但是最常用的小部件之一。

SizedBox as ConstrainedBox

​SizedBox​​​ 工作方式跟 ​​ConstrainedBox​​ 有些类似。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_sed_57

SizedBox.expand(
child: Card(
child: Text('Hello World!'),
color: Colors.yellowAccent,
),
),

SizedBox as padding

当需要添加内边距和外边距的时候,你可以选择 ​​Padding​​​ 或 ​​Container​​​ 小部件。但是,它们可以比添加 ​​Sizedbox​​ 更冗长且可读性更低。

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_58

Column(
children: <Widget>[
Icon(Icons.star, size: 50),
const SizedBox(height: 100),
Icon(Icons.star, size: 50),
Icon(Icons.star, size: 50),
],
),

SizedBox as an Invisible Object

很多时候,你想通过设置一个 ​​bool​​ 值来隐藏/展示小部件。

Show

Hide

Flutter 布局备忘录 -- 多图警告,干货建议收藏_ico_59

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_60

Widget build(BuildContext context) {
bool isVisible = true; // true or false
return Scaffold(
appBar: AppBar(
title: Text('isVisible = $isVisible'),
),
body: isVisible
? Icon(Icons.star, size: 150)
: const

因为 ​​SizedBox​​​ 有一个 ​​const​​​ 构造函数,所以使用 ​​const SizeBox()​​ 真的很便宜。一种更便宜的解决方案是使用 Opacity 小部件,将其 ​opacity​ 值更改为 ​0.0​。这种解决方案的缺点是给定的小部件只是不可见,但是还是占用空间。

SafeArea

在不同的平台,有些特定的区域,比如安卓的状态栏或者 ​​iPhone X​​ 的刘海区块,我们不应该在其下面绘制内容。

解决方案是使用 ​​SafeArea​​​ 小部件。(下面截图是没使用/使用 ​​SafeArea​​)

without

with

Flutter 布局备忘录 -- 多图警告,干货建议收藏_iOS_61

Flutter 布局备忘录 -- 多图警告,干货建议收藏_Android_62

Widget build(BuildContext context) {
return

本文翻译自 Flutter Layout Cheat Sheet​。代码已经验证,需要留意 ​​RaisedButton​​​ 已经被 ​​ElevatedButton​​ 替代,在现实使用中需要留意。本文重点是其布局思路和技巧。

举报

相关推荐

0 条评论