Responsive Flutter App with BuildContext — Dart extension#3

The next level to create a responsive layout with the context in all widget tree flutter.

Matatias Situmorang
6 min readFeb 12, 2023
Photo by Hal Gatewood on Unsplash

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.

Widget Tree

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:

mobile preview

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 pixels768 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:

tablet preview

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:

desktop preview

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 the xl value.
  • But when xl is null, we return the lg value.
  • If lg is null, we return the md value.
  • md is null return sm value.
  • sm is null return the defaultVal
  • 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:

Responsive layout screen.

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:

--

--

Matatias Situmorang

Flutter developer | Blogger | Reach me on twitter @pmatatias_