How can you make your application responsive?
#responsive#layout#ui#mediaquery
Answer
Overview
Making a Flutter app responsive means ensuring it looks good and works well across different screen sizes (phones, tablets, desktops) and orientations (portrait, landscape). Flutter provides several approaches to achieve responsive design.
1. MediaQuery - Get Screen Dimensions
text
MediaQuerydartclass ResponsiveWidget extends StatelessWidget { Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final width = size.width; final height = size.height; final orientation = MediaQuery.of(context).orientation; return Container( width: width * 0.8, // 80% of screen width height: height * 0.5, // 50% of screen height color: orientation == Orientation.portrait ? Colors.blue : Colors.red, ); } }
2. LayoutBuilder - Respond to Parent Constraints
text
LayoutBuilderdartLayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 600) { // Tablet/Desktop layout return Row( children: [ Expanded(child: SideBar()), Expanded(flex: 3, child: MainContent()), ], ); } else { // Mobile layout return Column( children: [ MainContent(), ], ); } }, )
3. Responsive Breakpoints
Define breakpoints for different screen sizes.
dartclass Breakpoints { static const double mobile = 600; static const double tablet = 900; static const double desktop = 1200; } class ResponsiveLayout extends StatelessWidget { final Widget mobile; final Widget? tablet; final Widget desktop; const ResponsiveLayout({ required this.mobile, this.tablet, required this.desktop, }); Widget build(BuildContext context) { return LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth >= Breakpoints.desktop) { return desktop; } else if (constraints.maxWidth >= Breakpoints.tablet) { return tablet ?? mobile; } else { return mobile; } }, ); } } // Usage ResponsiveLayout( mobile: MobileHomePage(), tablet: TabletHomePage(), desktop: DesktopHomePage(), )
4. Flexible & Expanded - Proportional Layouts
Use
text
Flexibletext
ExpandeddartRow( children: [ Expanded( flex: 2, child: Container(color: Colors.red), ), Expanded( flex: 1, child: Container(color: Colors.blue), ), ], )
5. AspectRatio - Maintain Proportions
dartAspectRatio( aspectRatio: 16 / 9, child: Container( color: Colors.purple, child: Center(child: Text('16:9 Video')), ), )
6. FractionallySizedBox - Percentage-based Sizing
dartFractionallySizedBox( widthFactor: 0.8, // 80% of parent width heightFactor: 0.5, // 50% of parent height child: Container(color: Colors.green), )
7. OrientationBuilder - Portrait vs Landscape
dartOrientationBuilder( builder: (context, orientation) { return GridView.count( crossAxisCount: orientation == Orientation.portrait ? 2 : 4, children: List.generate(20, (index) => Card(child: Text('$index'))), ); }, )
8. Responsive Packages
responsive_builder
dartimport 'package:responsive_builder/responsive_builder.dart'; ScreenTypeLayout.builder( mobile: (context) => MobileView(), tablet: (context) => TabletView(), desktop: (context) => DesktopView(), )
flutter_screenutil
dartimport 'package:flutter_screenutil/flutter_screenutil.dart'; // In main() ScreenUtil.init( BoxConstraints(maxWidth: 375, maxHeight: 812), designSize: Size(375, 812), ); // Usage Container( width: 200.w, // Responsive width height: 100.h, // Responsive height padding: EdgeInsets.all(16.r), // Responsive padding child: Text( 'Hello', style: TextStyle(fontSize: 24.sp), // Responsive font ), )
9. Responsive Font Sizes
dartdouble getResponsiveFontSize(BuildContext context, double baseSize) { final width = MediaQuery.of(context).size.width; if (width < 600) return baseSize; if (width < 900) return baseSize * 1.2; return baseSize * 1.5; } Text( 'Responsive Text', style: TextStyle( fontSize: getResponsiveFontSize(context, 16), ), )
10. Platform-Specific Layouts
dartimport 'dart:io'; Widget build(BuildContext context) { if (Platform.isAndroid || Platform.isIOS) { return MobileLayout(); } else if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { return DesktopLayout(); } else { return WebLayout(); } }
Best Practices
| Practice | Description |
|---|---|
| Mobile-first | Design for mobile, then scale up |
| Test on real devices | Emulators may not show all issues |
| Use constraints | Prefer text text |
| Avoid hardcoded sizes | Use percentages or constraints |
| Test orientations | Always test portrait and landscape |
| Use safe areas | Respect notches and system UI with text |
Complete Example
dartclass ResponsiveHomePage extends StatelessWidget { Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('Responsive App')), body: SafeArea( child: LayoutBuilder( builder: (context, constraints) { if (constraints.maxWidth > 900) { // Desktop: 3 columns return GridView.count( crossAxisCount: 3, padding: EdgeInsets.all(16), children: _buildItems(), ); } else if (constraints.maxWidth > 600) { // Tablet: 2 columns return GridView.count( crossAxisCount: 2, padding: EdgeInsets.all(16), children: _buildItems(), ); } else { // Mobile: 1 column return ListView( padding: EdgeInsets.all(16), children: _buildItems(), ); } }, ), ), ); } List<Widget> _buildItems() { return List.generate( 20, (index) => Card( child: Padding( padding: EdgeInsets.all(16), child: Text('Item $index'), ), ), ); } }
Summary
Use MediaQuery for screen info, LayoutBuilder for parent constraints, and breakpoints for device-specific layouts. Combine with Flexible/Expanded for proportional sizing and responsive packages for advanced features.
Learn more at Flutter Responsive Design.