Responsive Design for Flutter: Getting Started

In this Flutter Responsive Design tutorial you’ll learn how to build a Flutter app that responds to layout changes such as screen size and orientation. By JB Lorenzo.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 2 of this article. Click here to view the first page.

Auto-Resizing Text Based on Parent Widget Size

As you can see in the landscape screenshot above, the text in the colored boxes for the user isn’t resizing properly to fill the box. You can’t just increase the size of the font because you might go over the box. The right way to do it is to allow the widget to scale according to the size of the parent widget.

The Flutter widget FittedBox can solve this problem.

Using FittedBox

Open AvatarImageView.dart in lib/widgets and check the contents of _buildContent(Color textColor). You can see here a Text widget that renders the initials of the user. The font size is 14. Surround the Text widget with a FittedBox like below:

// 1
return FittedBox(
  // 2
  fit: BoxFit.contain,
  // 3
  child: Text(
    initials,
    style: TextStyle(color: textColor, fontSize: 14),
  ),
);

This makes the Text widget fill the parent widget and follows the BoxFit.contain rules. Going over each line:

  1. First, you declare a FittedBox as a parent of the Text widget.
  2. Second, you use the BoxFit.contain fit to make it scale as big as it can without going out of the widget box.
  3. Finally, you declare the original Text widget as a child.

Build and run the project. You’ll see the following in landscape orientation:

Resized text in landscape

Now you see that the text has resized accordingly. In general, you can use other types of BoxFit. You can see how each of them behave in the image below:

BoxFit options

Providing Constraints to Children

There’s a paper clip image attachment button in your chat app. This should allow you to select images from a gallery. Usually, you want to display it within the chat view so you can still see the conversation while picking an image.

Right now, this is not displaying. Click on the attach button and you’ll only see the following for portrait:

Gallery in starter portrait

and this for landscape:

Gallery in starter landscape

Using AspectRatio

You need to fix the broken gallery. First, open the ConversationPage.dart file in the lib folder. Then look for the line with SquareGallery() with a TODO.

That widget isn’t appearing because it’s a child of Column and it doesn’t have enough information to determine its own height. So, wrap it in a AspectRatio widget to give it constraints. Replace the SquareGallery() line with the following:

AspectRatio(
  aspectRatio: 3,
  child: SquareGallery(),
),

Now that the gallery is wrapped in AspectRatio, it’ll have a constraint that tries to follow the provided ratio. It’ll be three times wider than it is high. In addition, AspectRatio will try to find constraints that fit what you provided as ratio as well as the parent constraints.

However, if it can’t find such a constraint, it’ll give you one that follows only the ratio you provided. In that case, the widget might overflow.

Build and run the project. When clicking the image attachment button, you should see a screen like this for portrait:

Gallery final portrait

and this for landscape:

Gallery final landscape

Congratulations! Now you’ve fixed the layout issues in the app. You can finally be responsive again in the chats! :]

CustomMultiChildLayout

In addition to the basic widgets for responsive design, Flutter also provides a way to layout widgets on your own with CustomMultiChildLayout. You’ll now see how to use it, but only in theory. Because CustomMultiChildLayout is such a big topic, you’ll only see the basics here.

Check out the code snippet below:

CustomMultiChildLayout(
  delegate: delegate,
  children: widgets,
)

Here you declare a CustomMultiChildLayout with a custom delegate. The delegate can be an object of a class like the following:

// 1
class RWDelegate extends MultiChildLayoutDelegate {
  // 2
  @override
  void performLayout(Size size) {
    // Do your layout here
  }

  // 3
  @override
  bool shouldRelayout(MultiChildLayoutDelegate oldDelegate) => false;
}

Here’s what you did:

  1. First, you declare a subclass of MultiChildLayoutDelegate.
  2. Second, you override the performLayout method. Here you need to layout the children widgets using the layoutChild and positionChild methods.
  3. Finally, you return a boolean from shouldRelayout if the widget should perform a layout again. This method should decide based on your own widget’s parameters or state.

You can read the full docs for this widget here and for the delegate here. Look for a full tutorial on CustomMultiChildLayout on our Flutter page soon!

You can download the completed project by clicking on the Download Materials button at the top or bottom of the tutorial.

If you’re interested, check out the official docs for responsive apps in Flutter here and the official design cookbook here.

There’s also good guides on how to develop apps for various screen sizes and orientations here and here.

The Flutter team also made a presentation at Google I/O 2019 about adaptive UIs in Flutter. You can watch it here.

You also might want to read about the text accessibility settings on each platform.

I hope you enjoyed this tutorial on Responsive Design with Flutter! If you have any questions or comments, please join the forum discussion below.