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.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Responsive Design for Flutter: Getting Started
15 mins
- What is Responsive Design?
- Handling Different Device Types and Screen Sizes
- Handling Keyboard State Changes
- Handling Orientation Changes
- Getting Started
- Using MediaQuery to Decide the Layout
- Using Widgets in Responsive Design
- Using LayoutBuilder and OrientationBuilder
- Auto-Resizing Text Based on Parent Widget Size
- Using FittedBox
- Providing Constraints to Children
- Using AspectRatio
- CustomMultiChildLayout
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:
- First, you declare a
FittedBox
as a parent of theText
widget. - Second, you use the
BoxFit.contain
fit to make it scale as big as it can without going out of the widget box. - Finally, you declare the original
Text
widget as a child.
Build and run the project. You’ll see the following in landscape orientation:
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:
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:
and this for 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:
and this for 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:
- First, you declare a subclass of
MultiChildLayoutDelegate
. - Second, you override the
performLayout
method. Here you need to layout the children widgets using thelayoutChild
andpositionChild
methods. - 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.