Responsive Flutter App with BuildContext — Dart extension#3
The next level to create a responsive layout with the context in all widget tree flutter.
Welcome to the dart extension series. An article about the extension method I used while developing Flutter apps. In the previous article, I explored about Neumorphism Widget. If you missed it, you might read it through the link at the end of this article.
This is the third article; in this section, we will implement a BuildContext for creating a responsive flutter App. If you have been trying flutter, you may be familiar with the context. To make it clear:
BuildContext is A handle to the location of a widget in the widget tree.
if you wonder where you can see the widget tree, you can find it on the widget inspector while debugging the code. If you are running from the VSCode editor, you can find it from this button:
or if you run from terminal flutter run
you will get the link for the devtools page:
The Flutter DevTools debugger and profiler on your_device_name is available at: http://your_url_devtools/
Here I have a “Hello Word!” app in flutter.
Since context is handling widget location, then it will be available in all widgets. So, we have access to the context from all widgets rendered.
Ok, now we have a context. Next, with the context, we implement it for making responsive flutter widgets. In responsive terms, we are creating a condition to handle a widget in different widths of screens, right?
For example, I have a flutter app that will show 3 widgets on a screen.
- widget 1 will show with blue color,
- widget 2 with grey color,
- widget 3 with green color
Condition 1: We want to display all widgets on a mobile screen. In this case, the width of the screen is less than 640 pixels
. So, we will arrange the widget in Column
. See the image mobile preview below:
Condition 2: We want to display different views on a wider screen. In this case, we will handle the view for the tablet version. For this condition usually between 640 pixels
— 768 pixels
in width. Since we have wider screens than mobile, it's better to combine Column
and Row
for our widget. See the image tablet preview below:
Condition 3: To handle screens wider than 768 pixels
, we will arrange the widget all in Row
. For example, when we open the app on a desktop or laptop that has a widescreen. See the desktop preview below:
fyi: the preview image above was created with package: https://pub.dev/packages/device_preview
This is core of this article. The extension method of responsive widget:
extension Responsive on BuildContext {
T responsive<T>(
T defaultVal, {
T? sm,
T? md,
T? lg,
T? xl,
}) {
final wd = MediaQuery.of(this).size.width;
return wd >= 1280
? (xl ?? lg ?? md ?? sm ?? defaultVal)
: wd >= 1024
? (lg ?? md ?? sm ?? defaultVal)
: wd >= 768
? (md ?? sm ?? defaultVal)
: wd >= 640
? (sm ?? defaultVal)
: defaultVal;
}
}
code above is a method that extends on BuildContext
and with a generic type of data. defaultVal
is a required argument for the method. And there are 4 optional params as a breakpoint. This method uses MediaQuery
to get the width of the screen. You can customize the condition based on your need.
if you did not set any parameters, defaultVal
will be returned. For example, based on the 3 conditions we have above.
mobile:
≤ 640
pixel: which are we set to param sm
or in this case, we can set it as defaultVal
tablet:
≤ 768
pixel: we set to lg
param.
actually, for tablets no need to set the bottom margin like ≥ 640 pixel
. Because when the screen is less than 640 pixel
it will automatically be set to the sm
.
desktop:
> 768
pixel: In this condition, we will set to the lg
param. As you can see in the code if the screen is ≤1024 pixel
it will return lg
. And also, when in the first condition, when the screen width is ≥ 1280 pixel
it will return xl
, but since we didn't set the xl
than the lg
the value will return. It's because we use nested null
conditions. Ok, let me explain more. See the first condition:
wd >= 1280
? (xl ?? lg ?? md ?? sm ?? defaultVal)
which means:
- If the screen is wider than
1280 pixel,
we return thexl
value. - But when
xl
isnull,
we return thelg
value. - If
lg
isnull,
we return themd
value. md
isnull
returnsm
value.sm
isnull
return thedefaultVal
- since
defaultVal
is required, this is the last returned value.
— but if the screen is less then 1280 pixel
then it will go to the next condition which will check the screen is wider than 1024
pixel?
: wd >= 1024
I hope my explanation is clear enough. But if you are still confused, feel free to leave any questions. I’ll reply asap.
Implementation
this is a link to the demo in dartpad : https://dartpad.dev/?id=59656d666468db4c86d2c71362c6dcb4
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: context.responsive<Widget>(
mobileWidget, // default
md: tabletWidget, // medium
lg: desktopWidget, // large
),
);
}
and the result is:
another example with GridView.count
widget. To see if the logic works when all the parameters are set. So we can see the difference in all the different screen sizes.
Demo on dartpad : https://dartpad.dev/?id=925bbdc793dc6b529cb07eb636338ac9
See the code below:
@override
Widget build(BuildContext context) {
return GridView.count(
crossAxisCount: context.responsive<int>(
2, // default
sm: 2, // small
md: 3, // medium
lg: 4, // large
xl: 5, // extra large screen
),
and here is the result:
Thank you for having the end. I had a related article about the option to create a responsive layout in the flutter app. There are 3 options that you can choose from based on your need. Read full here:
As I mentioned before, this is the #3 article about the extension method. If you miss the #2 article read it about the Neumorphism flutter widget:
Btw, I will collect all the extension methods in the GitHub repository. You can get it through the link below. If you have an extension method and want to share it, feel free to contribute to this repository.
Some references for more reads: