• Flutter Layout Cheat Sheet
  • Tomek Polański
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: EmilyQiRabbit
  • Proofreader: Smilemuffie, Suhanyujie

Do you need to know a simple layout template for Flutter? Now I will show you a series of code snippets of the Flutter layout that I have summarized. I’ll try to keep the code short and easy to understand, and I’ll give you renderings. But we still need to do it step by step — the template catalog will follow. I will focus more on the application of Flutter components rather than simply displaying them (Flutter Gallery does this very well!). If you have other questions about Flutter layout, or would like to share your code with me, please leave a comment!


directory

  • The Row and Column
  • IntrinsicWidth and IntrinsicHeight
  • Stack
  • Expanded
  • ConstrainedBox
  • Container
    • Decoration: BoxDecoration
    • Image: DecorationImage
    • Border: border
    • BorderRadius: borderRadius
    • Shape: BoxShape
    • BoxShadow:List<BoxShadow>
    • Gradient: RadialGradient
    • BackgroundBlendMode: BlendMode
  • SizedBox
  • SafeArea

The Row and Column

MainAxisAlignment

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

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

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

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

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

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

If you want to be different characters of baseline alignment, you should use CrossAxisAlignment. The 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,
    ),
  ],
),
Copy the code

CrossAxisAlignment

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

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

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

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

MainAxisSize

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

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

IntrinsicWidth and IntrinsicHeight

Want all parts in a row or column to be the same height/width as the tallest/widest part? Stop looking for it! Here’s the answer!

When you have this style of layout:

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'),),),),); }Copy the code

But you want all buttons to be the width of the widest button, just use IntrinsicWidth: 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'),),),),),); }Copy the code

If you need to have all parts equal height to the highest part, use the combination IntrinsicHeight and Row.


Stack

Great for stacking parts together

@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,
      ),
    ],
  );
}
Copy the code

If you want to use the pieces of your own, you would have to put them in the inside of the toy

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() [() [() [() }Copy the code

If you don’t want to guess the value of top or bottom, you can use LayoutBuilder to retrieve them

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

Expanded

Expanded can be used with the Flex\Flexbox layout and is great for allocating multi-element Spaces.

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,),),Copy the code

ConstrainedBox

By default, most components use as little space as possible:

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

ConstrainedBox enables the widget to use the desired free space.

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

You can use BoxConstraints to specify how much space the widget can use — by specifying the min/ Max attributes of height/width.

BoxConstraints. Expand will make the component use unlimited (all available) space unless otherwise specified:

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

The above code is equivalent to the following:

ConstrainedBox(
  constraints: BoxConstraints(
    minWidth: double.infinity,
    maxWidth: double.infinity,
    minHeight: 300,
    maxHeight: 300,
  ),
  child: const Card(
    child: const Text('Hello World! '), 
    color: Colors.yellow,
  ),
),
Copy the code

Container

One of the most commonly used parts — and there’s a reason it’s so commonly used:

Container for the layout tool

If you do not specify the height and width of the Container, it will be the same size as the child

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(title: Text('Container as a layout')),
    body: Container(
      color: Colors.yellowAccent,
      child: Text("Hi"),),); }Copy the code

If you want the Container to expand to equal its parent element, use double-.infinity for the height and width attributes

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

The adornment of the Container

You can use the color property to change the background color of a Container, but decoration and foregroundDecoration can do more. (With these two properties, you can completely change the look of the Container, which I’ll discuss later because there’s a lot to cover.) Decorations are always placed after children, while foregrounddecorations are placed above them.

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

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

The change of the Container

If you don’t want to use the Transform widget to change your layout, you can use the Transform property of the Container

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,
      ),
    ),
  );
}
Copy the code

BoxDecoration

Decorator effects are usually used on container components to change the appearance of the component.

Image: DecorationImage

With the picture as the background:

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',),),),),),);Copy the code

Border: border

Specifies the container’s border style.

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(), ((), ((), ((), ((), (()Copy the code

BorderRadius: borderRadius

Let the border be rounded.

If decoratedshapeBoxShape.circle, thenborderRadiusWill be invalid

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))),),),);Copy the code

Shape: BoxShape

Boxes can be rectangular, square, oval or round in shape.

For any other shape, you should useShapeDecorationRather thanBoxDecoration

Scaffold(
  appBar: AppBar(title: Text('shape: BoxShape')),
  body: Center(
    child: Container(
      height: 200,
      width: 200,
      decoration: BoxDecoration(
        color: Colors.yellow,
        shape: BoxShape.circle,
      ),
    ),
  ),
);
Copy the code

BoxShadow:List<BoxShadow>

You can add a shadow to the container.

This parameter is a list so that you can define many different shadows and then combine them together.

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),],),),),);Copy the code

Gradient

There are three types of gradients: LinearGradient, RadialGradient, and 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,
          ],
        ),
      ),
    ),
  ),
);
Copy the code

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],),),),),);Copy the code

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],),),),),);Copy the code

backgroundBlendMode

BackgroundBlendMode is the most complex property in the BoxDecoration. It can mix the colors and gradients of the BoxDecoration, regardless of which element it is on.

With backgroundBlendMode, you can use a long list of algorithms in the BlendMode enumeration type.

First, configure the BoxDecoration as the foregroundDecoration, which is rendered above the child element of the Container (while the decoration is rendered after the child element).

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'(), (), (), ();Copy the code

BackgroundBlendMode affects more than just the Container in which it resides.

BackgroundBlendMode can change the color of any part in the part tree of a Container. In this code, we have a parent Container that renders an image image and a child Container that uses backgroundBlendMode. You will still get the same effect as the previous code.

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,
            ],
          ),
        ),
      ),
    ),
  ),
);
Copy the code

SizedBox

This is the simplest but most useful component

SizedBox for ConstrainedBox

SizedBox can achieve a similar effect to ConstrainedBox

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

A SizedBox used as an inside margin

If you need to add Padding or margins, you can use the Padding or Container widget. But none of them are as easy to read as adding a Sizedbox

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

A SizedBox used as an invisible object

Most of the time you want to control the display and hide of components with a Boolean value (bool)

Widget build(BuildContext context) {
  bool isVisible = ...
  return Scaffold(
    appBar: AppBar(
      title: Text('isVisible = $isVisible'),
    ),
    body: isVisible 
      ? Icon(Icons.star, size: 150) 
      : const SizedBox(),
  );
}
Copy the code

Since SizedBox has a const constructor, using const SizedBox() is very simple.

A simpler solution is to use the Opacity widget and change the value to 0.0. The disadvantage of this solution is that although the component is not visible, it still takes up space.


SafeArea

On different platforms, there are many specific locations, like the Android status bar or the iPhone X’s “bangs,” that should be avoided.

The solution is to use SafeArea parts (the following examples are with and without SafeArea)

Widget build(BuildContext context) {
  return Material(
    color: Colors.blue,
    child: SafeArea(
      child: SizedBox.expand(
        child: Card(color: Colors.yellowAccent),
      ),
    ),
  );
}
Copy the code

Stay tuned for more

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.