Tutorial

Creating a Basic Layout in Flutter

Published on September 6, 2019
author

Joshua Hall

Creating a Basic Layout in Flutter

As Flutter quickly becomes one of the leading technologies in app development, it is important for even someone in the web dev environment to check out. Coming from a background of HTML, CSS and JavaScript, the way Flutter handled everything seemed extremely foreign to me. So we’re going to be try and simplify it to just the essentials of structuring the elements in our app to create a simple layout using the Material Components.

Prerequisites

Already having Flutter installed and an emulator set up is necessary, we covered getting started in Flutter here. Becoming familiar with the official docs is also always a plus.

Scaffold

The Scaffold instantiates our main structure, usually whatever is consistent across our app like our appbar or navigation, then we’ll set our body to the more interesting part of our app, abstracting it out of runApp will also allow us to use hot reload.

main.dart
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text('I\'m an App'),
          backgroundColor: Colors.red[600],
        ),
        body: App(),
      ),
    ),
  );
}

class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container();
  }
}

And here’s what this looks like:

Scaffold

Containers

Like with HTML div’s, we can wrap our containers to give us more control over our elements when we can’t manipulate them themselves, since not every widget has properties like width or padding. Containers have some of the same properties from CSS like height, width, padding, and margin. By default, they will take up the maximum space of their children, empty containers try to take up the maximum amount of space of their parent.

Margin and Padding

Controlling the spacing can be a bit weird, instead of directly setting padding or margin to a number of pixels, we need to set it to a property on EdgeInsets and pass in our value in pixels. There is also the Padding widget that you can wrap your elements in, but you still need to pass-in padding the same as before so it’s really just to be explicit.

  • EdgeInsets.all()
  • EdgeInsets.only(left: 0, top: 0, right: 0, bottom: 0)
  • EdgeInsets.symmetric(vertical: 0, horizontal: 0)
  • EdgeInsets.fromLTRB(left, top, right, bottom) Just takes the values without them be explicitly assigned.
main.dart
class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Container(
      color: Colors.blue,
      margin: EdgeInsets.only(top: 20, right: 50),
      child: Container(
        color: Colors.green,
        // Add 200px on top and bottom
        margin: EdgeInsets.symmetric(vertical: 200),
        child: Container(
          color: Colors.yellow,
          margin: EdgeInsets.fromLTRB(0, 20, 200, 20),
        ),
      ),
    );
  }
}

And now we have a bunch of containers:

Screenshot of container

Columns and Rows

The problem with containers is that we can only have one child in each. The column and row widgets let us use a more flexible version of containers while controlling the direction of our elements. We can’t just pass child to them for each element, we need to set children to an array of the type <Widget>, then pass in each of our elements.

If we put a container inside of an Expanded widget, it will then take up the maximum amount of space of its column or row.

Similar to how flexbox works on the web, we can use mainAxisAlignment and crossAxisAlignment to do things the same as justify-content and align-items. We even have the same options of start, center, end, spaceEvenly, spaceAround, spaceBetween, and stretch.

main.dart
class App extends StatelessWidget {
  
  Widget build(BuildContext context) {
    return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          // Row 1
          Row(
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('2')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          ),
          // Row 2
          Row(
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              //Will expand to fill all remaining space
              Expanded(
                  child: Container(
                    color: Colors.green,
                    height: 40,
                    width: 40,
                    child: Text('2'))),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          ),
          //Row 3
          Container(
              height: 100,
              child: Row(
                //Stretches to vertically fill its parent container
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: <Widget>[
                  Container(
                    color: Colors.blue,
                    height: 40,
                    width: 40,
                    child: Text('1')),
                  Expanded(
                      child: Container(
                        color: Colors.green,
                        height: 40,
                        width: 40,
                        child: Text('2'))),
                  Container(
                    color: Colors.blue,
                    height: 40,
                    width: 40,
                    child: Text('3')),
                ],
              )),
          // Row 4
          Row(
            //Creates even space between each item and their parent container
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('1')),
              Container(
                color: Colors.blue, height: 40, width: 40, child: Text('3')),
            ],
          )
        ]);
  }
}

And here’s a screenshot of our rows and columns:

Screenshot of columns and Rows

Conclusion

While working with layouts in Flutter may seem a bit more clunky and verbose that on the web at first glance, it’s good to keep in mind that we also don’t have to deal with the complexity of dynamic grids or bloated media queries for every screen size. At times, layouts in Flutter may seem less powerful than the CSS you’re used to, because it really doesn’t have to be. With just a few containers, columns, rows, and spacing you can get most of the structures than you’ll ever need.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors
Default avatar
Joshua Hall

author

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
Leave a comment


This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

Try DigitalOcean for free

Click below to sign up and get $200 of credit to try our products over 60 days!

Sign up

Join the Tech Talk
Success! Thank you! Please check your email for further details.

Please complete your information!

Become a contributor for community

Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

DigitalOcean Documentation

Full documentation for every DigitalOcean product.

Resources for startups and SMBs

The Wave has everything you need to know about building a business, from raising funding to marketing your product.

Get our newsletter

Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

New accounts only. By submitting your email you agree to our Privacy Policy

The developer cloud

Scale up as you grow — whether you're running one virtual machine or ten thousand.

Get started for free

Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

*This promotional offer applies to new accounts only.