Flutter for Beginners: Our first Container.

Welcome to the third part of the Flutter for Beginners tutorial series. In this part, we will discuss the most commonly used widget, the container. This is one of the basic widgets that you will probably use in every project you created.


Series


In Flutter, a container is a widget that allows you to control the layout and appearance of its child widgets. It is used to wrap and contain other widgets within its boundaries. The Container widget provides properties for defining the size, alignment, padding, margin, and decoration of its child widget.

Now, let's update the code that we created in the previous episode to display the container instead of the hello world text.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("Hello Title"),
        ),
        body: Center(
          child: Container(
            width: 100,
            height: 100,
            color: Colors.red,
          ),
        ),
      ),
    );
  }

In the above code, we simply create a red Container, the width is 100 and the height is 100. Here is how it looks:

Flutter container

Just like the Center widget, the Container widget has a named parameter called child which you can pass another widget to it. As you can see, we're not defined the child of the container yet.

Working with BoxDecoration: Rounded corner with BorderRadius.

If we want to make the corner of the container rounded, we can use a border-radius. To add the border-radius, first, we need to define another parameter called decoration for our container. The decoration parameter accepts BoxDecoration as its parameter, which we can determine the border-radius to it.

Container(
    width: 100,
    height: 100,
    color: Colors.red,
    decoration: const BoxDecoration(
        borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
)

The code above looks good, but if we run it, an error will be displayed. The error says that we cannot provide both color and decoration parameters to the container. To solve this issue, we can just move the color property to inside BoxDecoration:

Container(
    width: 100,
    height: 100,
    decoration: const BoxDecoration(
    	color: Colors.red,
    	borderRadius: BorderRadius.all(Radius.circular(12)),
    ),
)

Now we have a box with rounded corners:

Flutter rounded container

Notice that we use BorderRadius.all method to define our border-radius, which mean it will be applied to all corner of the container.  

💡
Instead of using BorderRadius.all(Radius.circular(12)), we can use BorderRadius.circular(12). It will produce the same border radius for the container but with a simpler syntax.

What if we don't want to apply the border-radius to all corners? Here is how we do that:

Applying radius to a specific corner.
BoxDecoration(
    color: Colors.red,
    borderRadius: BorderRadius.only(
       topLeft: Radius.circular(12),
    ),
)

To apply the border-radius to a specific corner,  we can use BorderRadius.only to define the border radius. In the code above we use the topLeft parameter to define the top left corner border-radius.

As you may guess, we can define the border radius using topLeft, topRight, bottomLeft or bottomRight. Here is an example of using BorderRadius.only for more than one corner:

BorderRadius.only(
     topLeft: Radius.circular(12),
     bottomRight: Radius.circular(12),
)
Horizontally symmetrical border-radius.

We can also use BorderRadius.horizontal or BorderRadius.vertical to define our border-radius. BorderRadius.horizontal creates a horizontally symmetrical border-radius. Here is an example:

BorderRadius.horizontal(
   left: Radius.circular(12),
)

Again, as you may guess, the BorderRadius.horizontal accepts two parameters, left and right. As you can see in the image above, when we provide a radius into the left parameter, it will symmetrically set the radius of the left corners.

Vertically symmetrical border-radius.

The vertically symmetrical border-radius is very similar to the horizontal one. It uses BorderRadius.vertical that accepts two parameters, top and bottom.

BoxDecoration(
	color: Colors.red,
	borderRadius: BorderRadius.vertical(
		top: Radius.circular(12),
	),
)

Here is how it looks:

Border radius interpolation

There is one other way to set the value of the border-radius. We can use BorderRadius.lerp  to interpolate between to border-radius. This is usually used when we try to animate a border-radius.

BorderRadius.lerp(
	BorderRadius.circular(0),
	BorderRadius.circular(15),
	1,
)

There are three parameters, where the first one is the starting border-radius, the second one is the ending border-radius, and the third parameter is a value between 0.0 and 1.0 that represents the progress of the interpolation. A value of 0.0 corresponds to the starting BorderRadius, and a value of 1.0 corresponds to the ending BorderRadius . We will discuss more about how to animate objects in the following articles.

Working with Elliptical Radius

So far, we only work with circular radius with Radius.circular(n) syntax. There is one more type of radius called the elliptical radius. Unlike circular radius, which accepts only one parameter, the Radius.elliptical method accepts two. See the example below:

BoxDecoration(
	color: Colors.red,
	borderRadius: BorderRadius.vertical(
		top: Radius.elliptical(15, 60),
	),
)

Here is how it looks:

The first parameter is the x (horizontal radii) and the second one is the y (vertical radii).

Hopefully, the illustration above makes it clear how the Radius.elliptical works. In the example code above the y value is much larger than x (15, 60). That's why, the corner is not smoothly rounded. In case we use the Radius.circular , the x and y values are always equal.

Working with Padding

Padding is the empty space around the content of a widget.  To demonstrate how padding works in Container, let's define a child element first:

Container(
   width: 300,
   height: 300,
   padding: const EdgeInsets.all(30),
   color: Colors.red,
   child: Container(
       color: Colors.black,
   ),
),

Here is how it looks:

How Flutter padding works

As you can see in the image above, we have a red box with a black box in it. We set the padding using padding: parameter for all sides of the container to 30. Thus, the space between the child widget (the black box) and the edge of the container (the red box) is 30.

You should notice that we use EdgeInsets.all(30) to define the padding. EdgeInsets is a class that represents the inset distances for the edges of a rectangular area. The EdgeInsets class is often used not only for padding but also for margin.

Padding for specific sides

In the previous example, we define the same padding for all edges of the container. We can also set the specific padding for a specific side.  Here is an example:

Container(
    width: 300,
    height: 300,
    padding: const EdgeInsets.only(top: 30),
    color: Colors.red,
    child: Container(
       color: Colors.black,
    ),
)

This way, only the top edge of the container will have the padding.

The EdgeInsets.only method can accept more than one parameter. For example, you can provide top, bottom and left parameters at the same time.

Padding from Left, Top, Right, and Bottom (LTRB)

We can also set the specific padding for every edge of our container using EdgeInsets.fromLTRB. Here is how it works:

Container(
   width: 300,
   height: 300,
   padding: const EdgeInsets.fromLTRB(10, 20, 30, 40),
   color: Colors.red,
   child: Container(
       color: Colors.black,
   ),
)

fromLTRB is a named constructor in the EdgeInsets class. The constructor accepts four parameters. The left inset, top inset, right inset, and bottom inset.

Symmetrical Padding

In Flutter, we can create padding that is horizontally or vertically symmetrical using EdgeInsets.symmetric. For example:

Container(
   width: 300,
   height: 300,
   padding: const EdgeInsets.symmetric(vertical: 12),
   color: Colors.red,
   child: Container(
        color: Colors.black,
   ),
)

Here is the result:

As you can see in the image above, we use vertically symmetrical padding, so the top padding and the bottom padding will have the same value. You can also use horizontally symmetrical padding or horizontal and vertically symmetric padding at the same time.

edgeInsets.symmetric(horizontal: 12)
Horizontally symmetrical padding
edgeInsets.symmetric(vertical: 12, horizontal: 50)
Both horizontally symmetrical and vertically symmetrical padding

Working with margin

While the padding is the space between the child widget with the edge of the widget. Margin defines the space between the widget with the outside widget, like the parent widget and the siblings.

To demonstrate how margin works, let's create two boxes like so:

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text("Hello Title"),
        ),
        body: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              width: 200,
              height: 200,
              color: Colors.red,
            ),
            Container(
              width: 200,
              height: 200,
              color: Colors.blue,
            ),
          ],
        ),
      ),
    );
  }
Boxes with no margin

Notice that there is no space between the two boxes. Let's create a bottom margin for the red box with a value of 30.

Container(
	width: 200,
	height: 200,
	color: Colors.red,
	margin: const EdgeInsets.only(bottom: 30),
),

Now, there is space, between the two boxes. We can also display the same result by adding a top margin to the blue box. Notice that we use EdgeInsets.only to define the margin. It is the exact same EdgeInsets class that we used to define padding. Thus, we can also use EdgeInsets.fromLTRB , EdgeInsets.symmetric , etc.

💡
In Flutter, Column is a widget that displays its children in a vertical arrangement. It is used to create a vertical layout in which widgets are stacked one below the other.

As we mention before, the margin can not only define the space between boxes, but also between child and parent widget/screen. Let's modify the code a bit:

Container(
	width: 200,
	height: 200,
	color: Colors.red,
	margin: const EdgeInsets.fromLTRB(10, 20, 30, 40),
),

We use fromLTRB to define the inset. As you can see, now it is also define the space between the widget and the containing widget (the column). We cannot see the containing widget here, so let's say it is the space between the widget and the screen.

Conclusion

In this article, we discuss adding a border-radius to our container. We learn it using the BoxDecoration widget. Border radius is only one of the parameters that we can provide into BoxDecoration. We can use the BoxDecoration widget to define the container color, border, etc.

We also learn about padding and margin which are one of the most basic stylings of a Container.  In the next article, let's discuss the Stateless Widget vs the Stateful Widget.