Paramclasses Academy - Blog

Tutorials Details

←
Post 16 of 40
→

How to Create Responsive Flutter App Designs for Different Screen Sizes

How to Create Responsive Flutter App Designs for Different Screen Sizes

November 2, 2026

How to Create Responsive Flutter App Designs for Different Screen Sizes

❖ Welcome to Param Classes!

When we develop a mobile application, we cannot assume that every user has the same screen size. Some users have small mobile phones, others have large smartphones, and some may use tablets or foldable devices.

If an application looks perfect on one device but its buttons, images or text become too large or too small on another device, it creates a poor user experience.

This is why Responsive UI Design is important in Flutter app development.

Flutter provides different tools and widgets that help developers create interfaces that adjust according to available screen space.

In this tutorial, we will learn how to create responsive Flutter designs using:

  1. MediaQuery

  2. LayoutBuilder

  3. Expanded

  4. Flexible

  5. SingleChildScrollView

  6. Wrap

  7. Responsive layout examples

At Param Classes, we focus on practical programming knowledge so beginners can understand concepts and apply them in real projects.

Let's start!

✦ 1. What Is Responsive UI Design?

Responsive UI design means creating an application interface that adjusts according to the available screen size.

For example:

  • On a small mobile screen, buttons may appear vertically.

  • On a large mobile screen, buttons may appear horizontally.

  • On a tablet, the application may display two sections side by side.

  • Text and images should remain readable on different devices.

❖ Example of Responsive Design

Imagine you are creating a student dashboard.

On a mobile phone, you may display four dashboard cards in a single column.

On a tablet, you can display two cards in each row.

This makes the application easier to use without requiring completely separate designs for every device.

✦ 2. Understanding MediaQuery in Flutter

MediaQuery provides information about the current screen and its display environment.

You can use it to get:

  • Screen width

  • Screen height

  • Device pixel ratio

  • Text scaling information

  • Screen padding and safe areas

❖ MediaQuery Example

Create a Flutter project and open lib/main.dart.

Add this code:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.sizeOf(context).width;
    final screenHeight = MediaQuery.sizeOf(context).height;

    return Scaffold(
      appBar: AppBar(
        title: const Text('Responsive Flutter UI'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              'Screen Width: ${screenWidth.toStringAsFixed(0)}',
              style: const TextStyle(fontSize: 20),
            ),
            Text(
              'Screen Height: ${screenHeight.toStringAsFixed(0)}',
              style: const TextStyle(fontSize: 20),
            ),
          ],
        ),
      ),
    );
  }
}

❖ Understanding the Code

  • MediaQuery.sizeOf(context).width gets the available screen width.

  • MediaQuery.sizeOf(context).height gets the available screen height.

  • toStringAsFixed(0) displays the value without decimal places.

You can use these values to make layout decisions.

For example, if the available width is small, you may display content in a single column.

✦ 3. Set Widget Width According to Screen Size

Sometimes a fixed width does not work properly on different devices.

For example, a container with a width of 350 pixels may fit on one phone but overflow on a smaller screen.

Instead, calculate its width using MediaQuery.

❖ Responsive Container Example

Container(
  width: MediaQuery.sizeOf(context).width * 0.9,
  padding: const EdgeInsets.all(20),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(15),
  ),
  child: const Text(
    'Welcome to Param Classes',
    style: TextStyle(
      color: Colors.white,
      fontSize: 20,
    ),
  ),
)

Here, 0.9 means the container uses 90% of the available screen width.

This makes the container width flexible.

Tip: Use ConstrainedBox or Center with maxWidth constraints when you want content to stop growing beyond a comfortable width on larger screens.

✦ 4. Understanding LayoutBuilder in Flutter

LayoutBuilder helps you build a layout according to the constraints provided by its parent widget.

Unlike MediaQuery, which provides information about the screen, LayoutBuilder provides information about the available space in a particular part of the widget tree.

It is useful when a widget is inside a smaller container or a split-screen layout.

❖ LayoutBuilder Example

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: ResponsiveScreen(),
    );
  }
}

class ResponsiveScreen extends StatelessWidget {
  const ResponsiveScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('LayoutBuilder Example'),
      ),
      body: LayoutBuilder(
        builder: (context, constraints) {
          if (constraints.maxWidth < 600) {
            return const Center(
              child: Text(
                'Mobile Layout',
                style: TextStyle(fontSize: 25),
              ),
            );
          } else {
            return const Center(
              child: Text(
                'Tablet or Wide Layout',
                style: TextStyle(fontSize: 30),
              ),
            );
          }
        },
      ),
    );
  }
}

❖ Understanding the Code

  • LayoutBuilder receives the available layout constraints.

  • constraints.maxWidth gives the maximum available width.

  • If width is below 600, it displays the mobile layout.

  • Otherwise, it displays the wider layout.

The value 600 is an example breakpoint, not a fixed Flutter rule. Choose breakpoints based on your actual UI content.

✦ 5. Use Expanded for Responsive Layouts

The Expanded widget helps children of Row or Column use the available space.

It is useful when you want two or more sections to share space without setting fixed widths.

❖ Expanded Example

Row(
  children: [
    Expanded(
      child: Container(
        height: 120,
        color: Colors.blue,
        alignment: Alignment.center,
        child: const Text(
          'First Box',
          style: TextStyle(color: Colors.white),
        ),
      ),
    ),
    Expanded(
      child: Container(
        height: 120,
        color: Colors.orange,
        alignment: Alignment.center,
        child: const Text(
          'Second Box',
          style: TextStyle(color: Colors.white),
        ),
      ),
    ),
  ],
)

Both containers receive an equal share of the available horizontal space.

You can also control the space using flex.

Row(
  children: [
    Expanded(
      flex: 2,
      child: Container(height: 100, color: Colors.blue),
    ),
    Expanded(
      flex: 1,
      child: Container(height: 100, color: Colors.orange),
    ),
  ],
)

The first container receives twice the available space of the second container.

✦ 6. Understanding Flexible Widget

The Flexible widget is also used inside Row, Column or Flex.

It allows a child to use available space without necessarily forcing it to fill all that space.

❖ Flexible Example

Row(
  children: [
    Flexible(
      child: Container(
        color: Colors.blue,
        padding: const EdgeInsets.all(15),
        child: const Text(
          'This is a flexible content area.',
          style: TextStyle(color: Colors.white),
        ),
      ),
    ),
    const SizedBox(width: 10),
    const Icon(Icons.phone, size: 35),
  ],
)

❖ Expanded vs Flexible

Expanded Flexible
Forces its child to fill allocated space Allows its child to use available space
Uses tight fit by default Uses loose fit by default
Useful for equal-width sections Useful for content that can remain smaller

Both widgets help prevent layout problems when used correctly.

✦ 7. Use SingleChildScrollView for Small Screens

Sometimes a screen contains many input fields, buttons or other widgets.

On a smaller device, all the content may not fit vertically.

This can cause a RenderFlex overflow error.

You can use SingleChildScrollView to make the content scrollable.

❖ SingleChildScrollView Example

SingleChildScrollView(
  padding: const EdgeInsets.all(20),
  child: Column(
    children: [
      const Text(
        'Student Registration',
        style: TextStyle(fontSize: 25),
      ),
      const SizedBox(height: 20),
      const TextField(
        decoration: InputDecoration(
          labelText: 'Student Name',
          border: OutlineInputBorder(),
        ),
      ),
      const SizedBox(height: 15),
      const TextField(
        decoration: InputDecoration(
          labelText: 'Email Address',
          border: OutlineInputBorder(),
        ),
      ),
      const SizedBox(height: 15),
      const TextField(
        decoration: InputDecoration(
          labelText: 'Mobile Number',
          border: OutlineInputBorder(),
        ),
      ),
      const SizedBox(height: 20),
      ElevatedButton(
        onPressed: () {},
        child: const Text('Submit'),
      ),
    ],
  ),
)

Now users can scroll to view the complete form even when the screen is small.

For long lists of repeated items, prefer ListView.builder instead of placing a large number of children inside a SingleChildScrollView.

✦ 8. Use Wrap for Flexible Rows

The Wrap widget automatically moves children to the next line when there is not enough horizontal space.

It is useful for:

  • Category buttons

  • Product labels

  • Filter chips

  • Tags

  • Dashboard shortcuts

❖ Wrap Example

Wrap(
  spacing: 10,
  runSpacing: 10,
  children: [
    Chip(label: Text('Flutter')),
    Chip(label: Text('Dart')),
    Chip(label: Text('Android')),
    Chip(label: Text('PHP')),
    Chip(label: Text('MySQL')),
    Chip(label: Text('Firebase')),
  ],
)

❖ Important Properties

  • spacing: Horizontal space between children.

  • runSpacing: Vertical space between lines.

  • alignment: Controls alignment along the main axis.

  • children: Contains the widgets displayed inside Wrap.

Unlike Row, Wrap can move children onto multiple lines when required.

✦ 9. Practical Project: Create a Responsive Student Dashboard

Now let's combine the concepts and create a simple responsive student dashboard.

On smaller screens, dashboard cards will appear in one column. On wider screens, they will appear in two columns.

❖ Complete Code

Replace your lib/main.dart code with:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const DashboardScreen(),
    );
  }
}

class DashboardScreen extends StatelessWidget {
  const DashboardScreen({super.key});

  Widget dashboardCard(
    String title,
    IconData icon,
    Color color,
  ) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: color,
        borderRadius: BorderRadius.circular(15),
      ),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            icon,
            size: 40,
            color: Colors.white,
          ),
          const SizedBox(height: 10),
          Text(
            title,
            style: const TextStyle(
              color: Colors.white,
              fontSize: 18,
              fontWeight: FontWeight.bold,
            ),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Student Dashboard'),
      ),
      body: LayoutBuilder(
        builder: (context, constraints) {
          final isWide = constraints.maxWidth >= 600;

          return SingleChildScrollView(
            padding: const EdgeInsets.all(16),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const Text(
                  'Welcome, Student!',
                  style: TextStyle(
                    fontSize: 25,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 20),

                GridView.count(
                  crossAxisCount: isWide ? 2 : 1,
                  shrinkWrap: true,
                  physics:
                      const NeverScrollableScrollPhysics(),
                  crossAxisSpacing: 15,
                  mainAxisSpacing: 15,
                  childAspectRatio: isWide ? 2.5 : 2.2,
                  children: [
                    dashboardCard(
                      'My Courses',
                      Icons.book,
                      Colors.blue,
                    ),
                    dashboardCard(
                      'Assignments',
                      Icons.assignment,
                      Colors.orange,
                    ),
                    dashboardCard(
                      'My Results',
                      Icons.grade,
                      Colors.green,
                    ),
                    dashboardCard(
                      'My Profile',
                      Icons.person,
                      Colors.purple,
                    ),
                  ],
                ),
              ],
            ),
          );
        },
      ),
    );
  }
}

❖ Project Explanation

Let's understand the important parts:

1. LayoutBuilder

It checks the available width and decides which dashboard layout to display.

2. isWide Variable

final isWide = constraints.maxWidth >= 600;

If the available width is 600 or more, the layout uses two columns. Otherwise, it uses one column.

3. GridView.count

It creates a grid with a specific number of columns.

4. shrinkWrap

It allows the GridView to size itself according to its content in this example.

5. NeverScrollableScrollPhysics

It disables the GridView's own scrolling because the outer SingleChildScrollView handles scrolling.

6. childAspectRatio

It controls the width-to-height ratio of each dashboard card.

You can run this project on a mobile emulator and a wider device to observe how the dashboard changes.

✦ 10. Common Responsive Design Mistakes

Avoid these mistakes when developing Flutter applications:

  1. Using fixed widths everywhere: Fixed dimensions can cause overflow on smaller screens.

  2. Ignoring scrolling: Long forms and pages may not fit on small devices.

  3. Using Row for too many items: Consider Wrap or a responsive grid.

  4. Ignoring text scaling: Users may increase system text size, so test how your UI responds.

  5. Not testing on tablets: A mobile layout may not work well on a wider screen.

  6. Using too many screen-based calculations: Choose widgets that naturally adapt to available constraints whenever possible.

✦ 11. Practice Tasks for Beginners

Try these practical exercises:

  1. Use MediaQuery to display the screen width and height.

  2. Create a container that uses 80% of the available width.

  3. Use LayoutBuilder to display different text on mobile and tablet layouts.

  4. Create two equal sections using Expanded.

  5. Build a registration form using SingleChildScrollView.

  6. Display category chips using Wrap.

  7. Create a responsive dashboard with four cards.

❖ Conclusion

Responsive design is an important part of professional Flutter app development. A good application should provide a comfortable experience on different screen sizes.

In this tutorial, we learned how to use MediaQuery, LayoutBuilder, Expanded, Flexible, SingleChildScrollView and Wrap. We also created a practical student dashboard that changes its layout according to available screen width.

At Param Classes, we encourage beginners to practise these concepts by building real application screens. Once you understand responsive layouts, you can create better dashboards, registration forms, shopping applications and other mobile interfaces.

Learn Today, Grow Tomorrow with Param Classes!

←
Post 16 of 40
→