持续创作,加快成长!这是我参加「日新计划 6 月更文挑战」的第1天,点击检查活动详情

你是否需求了解 Flutter 布局的事例?

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

本文注重 Flutter 部件中比较有用的一些来展现,而不是蜻蜓点水展现一大推的部件内容。

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

Row and Column

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

MainAxisAlignment

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

假如你需求文本是针对基线对齐,那么你应该运用 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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
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 布局备忘录 -- 多图警告,干货建议收藏

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

同理,假如你想一切的部件的高度跟最高的部件一样高,你需求结合 IntrinsicHeightRow 来完成。

Stack

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

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

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

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

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

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

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

ConstrainedBox 允许小部件根据需求运用剩下的空间。

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

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

运用 BoxConstraints,你能够指定一个小部件能够有多少空间,你能够指定高度/宽度的最小/最大值。

除非指定值,不然 BoxConstraints.expand 运用无限的空间量(也就是运用剩下的一切空间):

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

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

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

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

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

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

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

你能够运用 Containercolor 特点来更改其布景色彩,可是你也能够运用 decorationforegroundDecoration 来更改。(运用这两个特点,你完全能够更改 Container 的姿态,这个咱们迟点说)。

decoration 总是在 child 特点的后边,而 foregroundDecoration 总是在 child 特点的后边。(这也不一定)

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

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

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

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

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(
              '', // 地址现已无效
            ),
          ),
        ),
      ),
    ),
  );
}

border: Border

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

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

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

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

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

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

有三种类型的突变:LinearGradientRadialGradientSweepGradient

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

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 [
              Colors.red,
              Colors.blue,
            ],
          ),
        ),
      ),
    ),
  );
}

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

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

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

backgroundBlendModeBoxDecoration 中最杂乱的特点之一。

它负责将 BoxDecoration 中色彩/突变,以及 BoxDecoration 上的任何内容混合一同。

运用 backgroundBlendMode, 你能够运用 BlendMode 枚举中指定的一长串算法。

首先,让咱们将 BoxDecoration 设置为 foregroundDecoration,它被制作在 Container 子部件之上(而 decoration 会制作在子部件之后)。

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

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(
          '', // 图片 404
        ),
      ),
    ),
  );
}

backgroundBlendMode 不仅仅影响它地点的 Container

backgroundBlendMode 改变其地点 Container 及其一下部件树的内容的色彩。

下面的代码又一个父部件 Container 来制作一个 image,然后有一个子部件 Container 来运用 backgroundBlendMode,可是你还是获取到和之前的作用。

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

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('backgroundBlendMode')),
    body: Center(
      child: Container(
        decoration: BoxDecoration(
          image: DecorationImage(
            image: NetworkImage(
              '', // 404
            ),
          ),
        ),
        child: Container(
          height: 200,
          width: 200,
          foregroundDecoration: BoxDecoration(
            backgroundBlendMode: BlendMode.exclusion,
            gradient: LinearGradient(
              colors: const [
                Colors.red,
                Colors.blue,
              ],
            ),
          ),
        ),
      ),
    ),
  );
}

Material

有切角的边框。

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

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

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

假如没运用 SliverFillRemaining,内容将会像下面这样溢出:

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

Filling the remaining space

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

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

假如没有满足的空间,部件将变为可翻滚。

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

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

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

SizedBox as padding

当需求增加内边距和外边距的时候,你能够选择 PaddingContainer 小部件。可是,它们能够比增加 Sizedbox 更冗长且可读性更低。

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

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

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

SafeArea

在不同的平台,有些特定的区域,比方安卓的状态栏或许 iPhone X 的刘海区块,咱们不应该在其下面制作内容。

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

without with
Flutter 布局备忘录 -- 多图警告,干货建议收藏
Flutter 布局备忘录 -- 多图警告,干货建议收藏
Widget build(BuildContext context) {
  return Material(
    color: Colors.blue,
    child: SafeArea(
      child: SizedBox.expand(
        child: Card(color: Colors.yellowAccent),
      ),
    ),
  );
}

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