Skip to main content

Building Responsive UIs

1. Using MediaQuery Class

Property Description Values
MediaQuery.of(context) Retrieves the current media properties MediaQueryData
size Gets the size of the screen Size
orientation Gets the screen orientation Orientation.portrait or Orientation.landscape
padding Gets the padding for the screen (e.g., status bar, navigation bar) EdgeInsets
textScaleFactor Gets the current text scale factor double

Example: Using MediaQuery to get screen size

import 'package:flutter/material.dart';

class ResponsiveScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Text(
          "Screen size: ${MediaQuery.of(context).size.width} x ${MediaQuery.of(context).size.height}",
        ),
      ),
    );
  }
}
Note: MediaQuery is a powerful tool for building responsive UIs in Flutter. It provides access to various screen properties that can be used to adjust layouts dynamically.

2. Using LayoutBuilder Widget

The LayoutBuilder widget is a powerful tool for creating responsive UIs in Flutter. It allows you to build layouts that adapt based on the available space provided by its parent.

Property Description Values
builder The callback that builds the widget tree using the constraints provided by the parent. Widget Function(BuildContext, BoxConstraints)

Example: Using LayoutBuilder to adapt layout based on screen size

<div class="example">
  <h3>Example: Using LayoutBuilder to adapt layout based on screen size</h3>
  <div class="codeBlock" data-language="dart">
    <pre><code>import 'package:flutter/material.dart';

class ResponsiveLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth < 600) {
          return Column(
            children: [
              Text('Mobile View'),
              Text('Content here'),
            ],
          );
        } else {
          return Row(
            children: [
              Text('Desktop View'),
              Text('Content here'),
            ],
          );
        }
      },
    );
  }
}</code></pre>
  </div>
</div>

3. Using OrientationBuilder Widget

Property Description Usage
orientation The current device orientation (portrait or landscape) Orientation.portrait or Orientation.landscape

Example: Using OrientationBuilder

OrientationBuilder(
  builder: (context, orientation) {
    return Container(
      color: orientation == Orientation.portrait
          ? Colors.blue
          : Colors.green,
      child: Center(
        child: Text(
          "Orientation: ${orientation.name}",
        ),
      ),
    );
  },
)
Note: OrientationBuilder rebuilds the widget whenever the device orientation changes.

4. Creating Breakpoint-Based Layouts

Breakpoint Device Type Width Range (px) Usage
xs Mobile < 600 Small mobile screens, portrait mode
sm Mobile 600 - 959 Portrait and landscape mobile
md Tablet 960 - 1279 Tablet in portrait or landscape
lg Desktop 1280 - 1919 Desktop and large screens
xl Large Desktop >= 1920 Very large screens, ultra-wide displays

Example: Using Breakpoints in Layout

import &#x27;package:flutter/material.dart&#x27;;

class ResponsiveLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth < 600) {
          return Text("Mobile View");
        } else if (constraints.maxWidth < 960) {
          return Text("Tablet View");
        } else {
          return Text("Desktop View");
        }
      },
    );
  }
}

Example: Responsive Grid with Breakpoints

import &#x27;package:flutter/material.dart&#x27;;

class ResponsiveGrid extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GridView.count(
      crossAxisCount: MediaQuery.of(context).size.width < 600 ? 1 : 2,
      children: List.generate(4, (index) {
        return Card(
          child: Center(child: Text("Item $index")),
        );
      }),
    );
  }
}
Note: Use LayoutBuilder for more complex responsive logic that depends on the parent's constraints rather than screen size.

5. Using ResponsiveBuilder Patterns

The ResponsiveBuilder is a powerful widget in Flutter that allows you to build responsive UIs by detecting the screen size and adjusting the layout accordingly. It provides a clean way to adapt your UI based on different device types (mobile, tablet, desktop).

Property Description Values
builder The builder function that returns the widget to be built based on screen size. Function<BuildContext, ScreenSize> → Widget
breakpoints Custom breakpoints to define screen size ranges. Map<String, BoxConstraints>

Example: Basic ResponsiveBuilder Usage

ResponsiveBuilder(
  builder: (context, sizingInformation) {
    if (sizingInformation.screenSize == ScreenSize.small) {
      return Text('Small screen');
    } else if (sizingInformation.screenSize == ScreenSize.medium) {
      return Text('Medium screen');
    } else {
      return Text('Large screen');
    }
  },
)

Example: Using Breakpoints

ResponsiveBuilder(
  breakpoints: {
    'mobile': const BoxConstraints(maxWidth: 600),
    'tablet': const BoxConstraints(minWidth: 601, maxWidth: 1024),
    'desktop': const BoxConstraints(minWidth: 1025),
  },
  builder: (context, sizingInformation) {
    return Text('Current size: ${sizingInformation.screenSize}');
  },
)
Note: The ResponsiveBuilder uses LayoutBuilder internally to determine screen size, so it's reactive to changes in device orientation or window size.

Key Features of ResponsiveBuilder

  • Automatically detects screen size categories (small, medium, large)
  • Supports custom breakpoints for fine-grained control
  • Provides ScreenSize enum to identify current screen size
  • Works with any widget tree inside the builder function

6. Using Flexible and Expanded Widgets

Widget Description Usage
Flexible Allows a child of a Row, Column, or Stack to expand and fill the available space.
Flexible(
  child: Container(
    color: Colors.blue,
  ),
)
Expanded Similar to Flexible but takes up all available space in the parent's main axis direction.
Expanded(
  child: Container(
    color: Colors.red,
  ),
)

Example: Flexible and Expanded in a Row

Row(
  children: [
    Container(
      color: Colors.green,
      width: 100,
    ),
    Flexible(
      child: Container(
        color: Colors.blue,
        height: 100,
      ),
    ),
    Expanded(
      child: Container(
        color: Colors.red,
        height: 100,
      ),
    ),
  ],
)
Note: Flexible allows its child to expand and shrink, while Expanded forces its child to fill the available space.

7. Creating Adaptive Layouts

Property Description Values
LayoutBuilder Builds a widget tree based on the available layout constraints Widget build(BuildContext context)
MediaQuery Provides information about the current device's screen size and orientation MediaQueryData data = MediaQuery.of(context)
Orientation Represents the screen orientation (portrait or landscape) Orientation.portrait, Orientation.landscape
Breakpoint Defines screen size thresholds for adaptive layouts Breakpoint.small, Breakpoint.medium, Breakpoint.large

Example: Using LayoutBuilder

class AdaptiveLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (context, constraints) {
        if (constraints.maxWidth < 600) {
          return Column(
            children: [
              Text('Mobile View'),
              Text('Content here'),
            ],
          );
        } else {
          return Row(
            children: [
              Text('Desktop View'),
              Text('Content here'),
            ],
          );
        }
      },
    );
  }
}

Example: Using MediaQuery

class ResponsiveWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final orientation = MediaQuery.of(context).orientation;
    return Container(
      child: orientation == Orientation.portrait
          ? Text('Portrait Mode')
          : Text('Landscape Mode'),
    );
  }
}
Note: LayoutBuilder is preferred over MediaQuery for adaptive layouts because it responds to changes in constraints rather than screen size alone.

8. Using Platform-Specific Widgets

Widget Description Platform Support
MaterialApp Flutter's Material Design implementation for Android and web. Android Web
CupertinoApp Flutter's iOS-style Cupertino widgets for iOS and web. iOS Web
PlatformWidget Allows custom rendering based on the platform. All

Example: Platform-Specific Widget Usage

import &#x27;package:flutter/foundation.dart&#x27;;
import &#x27;package:flutter/material.dart&#x27;;

Widget build(BuildContext context) {
  return PlatformWidget(
    android: (context) => MaterialButton(
      onPressed: () {},
      child: Text("Android Button"),
    ),
    ios: (context) => CupertinoButton(
      onPressed: () {},
      child: Text("iOS Button"),
    ),
  );
}
Note: Use defaultTargetPlatform to detect the current platform in code.

Platform-Specific Widget Summary

  • MaterialApp is used for Material Design on Android and web.
  • CupertinoApp is used for iOS-style widgets on iOS and web.
  • PlatformWidget allows conditional rendering based on platform.

9. Implementing Responsive Text Sizes

Property Values Description
TextTheme.displayLarge TextStyle(fontSize: 96.0) Large display text for headlines
TextTheme.displayMedium TextStyle(fontSize: 60.0) Medium display text
TextTheme.displaySmall TextStyle(fontSize: 48.0) Small display text
TextTheme.headlineLarge TextStyle(fontSize: 32.0) Large headline text
TextTheme.headlineMedium TextStyle(fontSize: 24.0) Medium headline text
TextTheme.headlineSmall TextStyle(fontSize: 20.0) Small headline text
TextTheme.titleLarge TextStyle(fontSize: 20.0) Large title text
TextTheme.titleMedium TextStyle(fontSize: 16.0) Medium title text
TextTheme.titleSmall TextStyle(fontSize: 14.0) Small title text
TextTheme.bodyLarge TextStyle(fontSize: 16.0) Large body text
TextTheme.bodyMedium TextStyle(fontSize: 14.0) Medium body text
TextTheme.bodySmall TextStyle(fontSize: 12.0) Small body text

Example: Using Responsive Text in Flutter

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Responsive Text Demo',
      theme: ThemeData(
        useMaterial3: true,
        textTheme: const TextTheme(
          headlineLarge: TextStyle(fontSize: 32.0),
          titleMedium: TextStyle(fontSize: 16.0),
          bodyLarge: TextStyle(fontSize: 14.0),
        ),
      ),
      home: Scaffold(
        appBar: AppBar(title: Text("Responsive Text Example")),
        body: Padding(
          padding: EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text("Headline Large", style: Theme.of(context).textTheme.headlineLarge),
              SizedBox(height: 10),
              Text("Title Medium", style: Theme.of(context).textTheme.titleMedium),
              SizedBox(height: 10),
              Text("Body Large", style: Theme.of(context).textTheme.bodyLarge),
            ],
          ),
        ),
      ),
    );
  }
}
Note: Use TextTheme to define consistent text styles across your app. Flutter provides built-in text themes that adapt to different screen sizes and device configurations.

10. Testing Different Screen Sizes

Example: Using Flutter's Device Preview

import 'package:flutter/material.dart';
import 'package:device_preview/device_preview.dart';

void main() {
  runApp(
    DevicePreview(
      enabled: true,
      builder: (context) => MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      useRootNavigator: false,
      home: Scaffold(
        appBar: AppBar(title: Text('Responsive UI')),
        body: Center(child: Text('Hello, Flutter!')),
      ),
    );
  }
}
Device Screen Size (px) Pixel Ratio Notes
iPhone SE (2nd gen) 375 x 667 2.0 Small screen, 16:9 aspect ratio
iPhone 12 Pro Max 428 x 926 3.0 Large screen, 19:9 aspect ratio
iPad Air 834 x 1194 2.0 Tablet, 4:3 aspect ratio
Samsung Galaxy S21 360 x 800 3.0 Android, 16:9 aspect ratio
Note: Use MediaQuery to dynamically adjust layout based on screen size.

Workflow: Responsive Layout Testing

  1. Use DevicePreview to simulate various devices
  2. Implement LayoutBuilder or MediaQuery for adaptive UI
  3. Test on real devices or emulators with different screen sizes

Was this article helpful?