Adding Responsiveness to your Flutter widgets
Responsive UI changes the UI of the application screen/widget according to the size of the different mobile screens. Responsive UI is very useful when the same application is made for mobile, web, table, watch(wear apps). Responsive UI rearrange the UI according to the orientation of the device and size.
Need Of Responsive UI :
- Highly flexible design
- Provides optimized view according to the screen constraints or Orientation
- Minimalism in design
- Relatively cheap
- Easy for SEO
Table of content
Contributing factors used to create responsive UI:-
LayoutBuilder
Layout Builder changes the UI according to the size constraints of the device screen. Layout builder takes a builder which return a widget and change the view according to the condition specified by the user.
builder
takes a Buildcontext
and BoxConstraints
.
Here we are using the maxWidth
to change the UI of the screen. Whenever the width of the screen is less than 601 or greater than 600 the layout builder will return the VerticalView()
widget and HorizontalView()
widget respectively.
LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 601) {
return HorizontalView();
} else {
return VerticalView();
}},),
BoxConstraints
- Creates box constraints with the given constraints.
- Click here to read more about the
BoxConstraints
class. - We can also get the
maxWidth
,minWidth
,maxHeight
,minHeight
.
We can also change the UI by getting the Height and Width of the device screen. Example:-
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 601) {
return HorizontalView();
} else {
return VerticalView();
}},),);}}
Widget VerticalView() {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue.withOpacity(0.3),
elevation: 0,
title: Container(
width: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.favorite_border),
Icon(Icons.bookmark_border),
Icon(Icons.star_border),
],),),),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[Text("Hello"), Text("World")],),),);}
Widget HorizontalView() {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
NavigationRail(
backgroundColor: Colors.blue.withOpacity(0.3),
destinations: [
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),],
selectedIndex: 1,),
Text("Hello"),
Text("World ")
],),),);}
MediaQuery
MediaQuery is the class that enables us to query the current size of the media. We can use MediaQueryData.size
it to get the size of the screen. This will automatically rebuild whenever the MediaQueryData
changes.
MediaQueryData mediaQueryData(BuildContext context) {
return MediaQuery.of(context);
}
Size size(BuildContext buildContext) {
return mediaQueryData(buildContext).size;
}
double width(BuildContext buildContext) {
return size(buildContext).width;
}
double height(BuildContext buildContext) {
return size(buildContext).height;
}
MediaQuery.of(context)
returns theMediaQueryData
(eg. size of the screen, brightness mode, devicePixelRatio, etc).MediaQuery.of(context).size.width
gives us the width.MediaQuery.of(context).size.height
gives us the height of the current media.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth >= 601) {
return HorizontalView(
height(context) * 0.25, width(context) * 0.25);
} else {
return VerticalView(height(context) * 0.25, width(context) * 0.25);
}
},
),
);
}
}
Widget VerticalView(double height, double width) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue.withOpacity(0.3),
elevation: 0,
title: Container(
width: 150,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(Icons.favorite_border),
Icon(Icons.bookmark_border),
Icon(Icons.star_border),
],
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Container(
width: width,
height: height,
color: Colors.orange,
child: Center(child: Text("Hello")),
),
Container(
width: width,
height: height,
color: Colors.orange,
child: Center(child: Text("World")),
)
],
),
),
);
}
Widget HorizontalView(double height, double width) {
return Scaffold(
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
NavigationRail(
backgroundColor: Colors.blue.withOpacity(0.3),
destinations: [
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('First'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Second'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Third'),
),
],
selectedIndex: 1,
),
Container(
width: width,
height: height,
color: Colors.orange,
child: Center(child: Text("Hello")),
),
Container(
width: width,
height: height,
color: Colors.orange,
child: Center(child: Text("World")),
)
],
),
),
);
}
AspectRatio
Creates a widget with a specific aspect ratio. The aspectRatio
argument must not be null. The aspect ratio is expressed as a ratio of width to height. For example, a 19:7 width: height aspect ratio would have a value of 19.0/7.0.
class ApRatio extends StatelessWidget {
final double aspectRatio;
ApRatio({@required this.aspectRatio});
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: aspectRatio,
child: Container(
color: Colors.orange,
child: Center(child: Text("Aspect Ratio")),
),
);
}
}
FittedBox
It creates a widget that scales and positions its child within itself according to fit. The fit
and alignment
arguments must not be null.
We can also set alignment property to properly align the child(eg. alignment: Alignment.bottomRight
or alignment: Alignment(1.0, 1.0))
BoxFit Enums
BoxFit enum
How a box should be inscribed into another box. See also: applyBoxFit, which applies the sizing semantics of these…api.flutter.dev
Card(
child: Row(children: [
Text(
"Without fittedBox",
style: TextStyle(fontSize: 25),
),
Container(
height: 200,
child: Image.network(
"https://lh3.googleusercontent.com/-svwfeFI7WnY/XvHmVb955QI/AAAAAAAAHvc/K3JwOtoUkNkalWy_CY9DJRgxfKddCUQswCK8BGAsYHg/s0/Untitled-3.png"),
),
]),
),
FittedBox(
child: Card(
child: Row(
children: [
Text(
"With fittedBox",
style: TextStyle(fontSize: 25),
),
Container(
height: 200,
child: Image.network(
"https://lh3.googleusercontent.com/-svwfeFI7WnY/XvHmVb955QI/AAAAAAAAHvc/K3JwOtoUkNkalWy_CY9DJRgxfKddCUQswCK8BGAsYHg/s0/Untitled-3.png"),
),
],
),
),
),
FractionallySizedBox
It creates a widget that sizes its child to a fraction of the total available space.
If non-null, the widthFactor
and heightFactor
arguments must be non-negative.
Properties
heightFactor
(It is the height of the child. Its value lies between 0 to 1. IfheightFactor
: 0.5, it means the height of the child is 50% of the total height of the screen.)widthFactor
(It is the width of the child. Its value lies between 0 to 1. IfwidthFactor
: 0.5, it means the height of the child is 50% of the total width of the screen.)alignment
( It defines the position of the given child.)
FractionallySizedBox(
heightFactor: 1,
widthFactor: 0.25,
child: Container(color: Colors.green),
//in a row or column
Container(
height: 50.0,
child: Column(children: [
Flexible(
child: FractionallySizedBox(
heightFactor: 1,
widthFactor: 0.5,
child: Container(color: Colors.orange),
),
),
Flexible(
child: FractionallySizedBox(
heightFactor: 1,
widthFactor: 0.25,
child: Container(color: Colors.green)),
),
Flexible(
child: FractionallySizedBox(
heightFactor: 1,
widthFactor: 0.15,
child: Container(color: Colors.blue)),
),
])),
OrientationBuilder
It Creates an orientation builder. The builder
argument must not be null.
The orientation class provides us the landscape view, portrait view. We can use these views to check the device orientation and then we can change the app screen view as follows.
OrientationBuilder(
builder: (context, orientation) {
if (orientation == Orientation.landscape) {
return HorizontalView(
height(context) * 0.25, width(context) * 0.25);
} else {
return VerticalView(height(context) * 0.15, width(context) * 0.5);
}
},
),
Closing Thoughts
Responsive UIs are a Quintessential tool in modern applications as they provide us with the ease of customizing the User-Interface of the app as per the device’s screen size and orientation ensuring that the same app can be apparent run into multiple devices without any hindrance as the app will respond by rearranging the UI accordingly. The key purpose of this article is to avail you of an Insight into How we can create Responsive UIs In Your Flutter Widgets.
If you have not used the Responsive Approach, I hope this article has provided you with content information about what’s all about the topic, and you will give it — a Try. Initiate using Responsive UIs for your apps. !!!
Github Link:
flutter-devs/responsive_UI
A new Flutter application. This project is a starting point for a Flutter application. A few resources to get you…github.com
Thanks for reading this article ❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
Feel free to connect with us:
And read more articles from FlutterDevs.com.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.