Flutter — Effectively scale UI according to different screen sizes

Daniele Cambi
Flutter Community
Published in
5 min readMay 18, 2019

What is Flutter?

If you are here, you probably already have a good enough understanding of what Flutter is, the most important aspect that you’ve got to keep in mind while reading through this article, is that Flutter allows us to have full control of every single pixel displayed on the screen.

What’s this article about?

Since we have full control on all the pixels, we might want to draw a rectangle like this.

Container(
height: 40,
width: 60,
),

Great! We have a rectangle, but now, look at what happens if we display it on an iPhone 5s (4" Display) and on an iPhone XS Max (6,46" Display).

As you may noticed from the images above, the rectangle shown on the iPhone Xs Max is way smaller than the one displayed on the iPhone 5s.

That’s because Flutter won’t question whether the app is running on an iPhone 5s, an iPhone Xs Max or even a 13" iPad, the container will always be 40 x 60.

I got it, but how can I fix it?

Let’s solve the problem in a visual way first, then, once it is clear, we’ll get to the code.

Let’s take an empty view and then add a grid to it.

Now, we are going to refer to the cells of the grid as “Blocks

Finally we set the height and width of our rectangle using the blocks. This will allow us to have a consistent UI across every single display size, from an iPhone 5s to an iPad because for both of them we are going to have a 100 x 100 grid.

Let’s get to the code implementation!

Start creating a new dart file called ‘size_config.dart’, within it, define the SizeConfig class.

import ‘package:flutter/widgets.dart’;

class SizeConfig {}

We need to import ‘widgets.dart’ in order to use a very convenient class in Flutter that’s called MediaQueryData which holds the information of the current media, among which there is the size of our screen.

Now let’s define the properties we are going to use in this class.

import ‘package:flutter/widgets.dart’;class SizeConfig {
static MediaQueryData _mediaQueryData;
static double screenWidth;
static double screenHeight;
static double blockSizeHorizontal;
static double blockSizeVertical;
}

We need to initialize those values by writing a constructor function.

class SizeConfig {
static MediaQueryData _mediaQueryData;
static double screenWidth;
static double screenHeight;
static double blockSizeHorizontal;
static double blockSizeVertical;

void init(BuildContext context) {
_mediaQueryData = MediaQuery.of(context);
screenWidth = _mediaQueryData.size.width;
screenHeight = _mediaQueryData.size.height;
blockSizeHorizontal = screenWidth / 100;
blockSizeVertical = screenHeight / 100;
}
}

And this is pretty much it, all that’s left to do is to instantiate this object in your home screen.

class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
SizeConfig().init(context);

}
}

Finally use it to set the width and height of your container.

@override
Widget build(BuildContext context) {
return Center(
child: Container(
height: SizeConfig.blockSizeVertical * 20,
width: SizeConfig.blockSizeHorizontal * 50,
color: Colors.orange,
),
);
}

In the end we are basically saying that the rectangle should be 50% of the screen in width and 20% of the screen high.

And that’s pretty much all! This is the rectangle shown on an iPhone 5s and an iPhone XS Max.

Expanding on this concept

If you are a more experienced Flutter developer you may already have dealt with notches, status bars, navigation bars and all this stuff.

There’s a really convenient widget in flutter to deal with those in an efficient way, it is called ‘SafeArea’.

How do we account for SafeArea in our grid?

We start by adding a couple of fields into out ‘SizeConfig’ class to calculate the space taken by the SafeArea and remove it from the grid.

class SizeConfig {
static MediaQueryData _mediaQueryData;
static double screenWidth;
static double screenHeight;
static double blockSizeHorizontal;
static double blockSizeVertical;

static double _safeAreaHorizontal;
static double _safeAreaVertical;
static double safeBlockHorizontal;
static double safeBlockVertical;

void init(BuildContext context) {
_mediaQueryData = MediaQuery.of(context);
screenWidth = _mediaQueryData.size.width;
screenHeight = _mediaQueryData.size.height;
blockSizeHorizontal = screenWidth / 100;
blockSizeVertical = screenHeight / 100;

_safeAreaHorizontal = _mediaQueryData.padding.left +
_mediaQueryData.padding.right;
_safeAreaVertical = _mediaQueryData.padding.top +
_mediaQueryData.padding.bottom;
safeBlockHorizontal = (screenWidth -
_safeAreaHorizontal) / 100;
safeBlockVertical = (screenHeight -
_safeAreaVertical) / 100;
}
}

This will allow you to effectively scale the UI without worrying about the SafeArea.

What about scaling text?

Turns out you can use this very same grid for scaling text, I normally scale it using the SizeConfig.safeBlockHorizontal, but you can do it with the vertical one as well.

Here’s how it looks like.

GitHub link for the code shown in this article

All the code I have put in this article along with examples on how to use it, are available at

https://github.com/dancamdev/effectively_scale_UI_according_to_different_screen_sizes

Conclusion

So, this has been my very first article ever. I hope you enjoyed the article and most importantly, I hope you used what you’ve learned here to make many awesome, well scaled apps!

Who are you and where can I contact you?

You can find me on

- Instagram: Daniele Cambi (https://www.instagram.com/dancamdev/)
- Twitter: @dancamdev (https://twitter.com/dancamdev)
- Email: dancam.dev@gmail.com

Daniele Cambi (@dancamdev)

--

--

Daniele Cambi
Flutter Community

A native android developer, that is on it’s way to learn Flutter while sharing his journey with the community.