<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Dario Digregorio</title>
    <description>The latest articles on DEV Community by Dario Digregorio (@dariodigregorio).</description>
    <link>https://dev.to/dariodigregorio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1210753%2Ff0332093-f120-47b6-a35e-9c68bc81bd62.jpeg</url>
      <title>DEV Community: Dario Digregorio</title>
      <link>https://dev.to/dariodigregorio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dariodigregorio"/>
    <language>en</language>
    <item>
      <title>Mastering Responsive UIs in Flutter: The Full Guide</title>
      <dc:creator>Dario Digregorio</dc:creator>
      <pubDate>Sun, 25 Feb 2024 20:52:09 +0000</pubDate>
      <link>https://dev.to/dariodigregorio/mastering-responsive-uis-in-flutter-the-full-guide-3g6i</link>
      <guid>https://dev.to/dariodigregorio/mastering-responsive-uis-in-flutter-the-full-guide-3g6i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;💡 I recommend reading my article either in the &lt;a href="https://github.com/dario-digregorio/flutter_responsive" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; repository or on &lt;a href="https://dario-digregorio.medium.com/mastering-responsive-uis-in-flutter-the-full-guide-7e21acda614e" rel="noopener noreferrer"&gt;Medium&lt;/a&gt; because there you can also see video examples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Flutter has become a go-to framework for developing cross-platform apps, but the real challenge lies in making these apps responsive across a variety of devices. This article is all about mastering the world of Flutter to ensure your app looks and works great, whether on mobile, desktop, or web.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I was thrilled to see the community's enthusiastic response and the many insightful questions, when I released my first short guide on &lt;a href="https://dev.to/dariodigregorio/building-responsive-uis-in-flutter-a-short-guide-5871"&gt;Building Responsive UIs&lt;/a&gt;. So, I've put together this detailed follow-up to tackle all those burning questions. Whether you're just starting out or looking to improve your UI skills, this guide's got you covered!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;REPOSITORY&lt;/strong&gt;: &lt;a href="https://github.com/dario-digregorio/flutter_responsive" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; Here you will also find high resolution images, animations and gifs, which unfortunately are not supported on Dev.to&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg50vvtbm6jmupd2sk2fg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg50vvtbm6jmupd2sk2fg.png" alt="Responsive"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions, feedback, or suggestions, feel free to reach out to me &lt;a href="https://twitter.com/digregoriodario" rel="noopener noreferrer"&gt;on X/Twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side Note&lt;/strong&gt;: This guide avoids using additional packages. However, I recommend using at least a state management solution like Riverpod or Bloc to manage your app's state effectively. To keep this guide simple we will use the build in API &lt;code&gt;ChangeNotifier&lt;/code&gt; to update the UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Setup and Key Insights

&lt;ul&gt;
&lt;li&gt;
Recommended Emulators/Simulators or Devices

&lt;ul&gt;
&lt;li&gt;Your App doesn't support a Platform?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Some alternatives:&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

Foundation for Responsive Design

&lt;ul&gt;
&lt;li&gt;Mobile First&lt;/li&gt;
&lt;li&gt;Screen-based Breakpoints&lt;/li&gt;
&lt;li&gt;Device Segmentation&lt;/li&gt;
&lt;li&gt;Style File&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Basic Layout

&lt;ul&gt;
&lt;li&gt;Layout Foundation&lt;/li&gt;
&lt;li&gt;Building the Responsive Layout&lt;/li&gt;
&lt;li&gt;Adapting to Orientation Changes&lt;/li&gt;
&lt;li&gt;Dialogs&lt;/li&gt;
&lt;li&gt;Responsive Navigation&lt;/li&gt;
&lt;li&gt;Center ListView with whitespace&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Widgets

&lt;ul&gt;
&lt;li&gt;Single&lt;/li&gt;
&lt;li&gt;Multi&lt;/li&gt;
&lt;li&gt;Slivers&lt;/li&gt;
&lt;li&gt;Extras&lt;/li&gt;
&lt;li&gt;Responsive Text&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Adapting to different devices and platforms

&lt;ul&gt;
&lt;li&gt;
Notches and OS System Interfaces

&lt;ul&gt;
&lt;li&gt;Android&lt;/li&gt;
&lt;li&gt;iOS&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Orientation

&lt;ul&gt;
&lt;li&gt;How Orientation gets retrieved&lt;/li&gt;
&lt;li&gt;Device Orientation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Debugging&lt;/li&gt;

&lt;li&gt;Testing&lt;/li&gt;

&lt;li&gt;

Tips and Tricks

&lt;ul&gt;
&lt;li&gt;
Adaptive vs Responsive (Copied from Flutter Docs)

&lt;ul&gt;
&lt;li&gt;Responsive&lt;/li&gt;
&lt;li&gt;Adaptive&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Helpful Libraries&lt;/li&gt;

&lt;li&gt;Use a State Management Library&lt;/li&gt;

&lt;li&gt;Design a Prototype first&lt;/li&gt;

&lt;li&gt;

Hardcoded Sizes and Values

&lt;ul&gt;
&lt;li&gt;Why not just use &lt;code&gt;LayoutBuilder&lt;/code&gt; and &lt;code&gt;OrientationBuilder&lt;/code&gt;?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Flutter's versatility allows developers to target a wide range of platforms including iOS, Android, Web, Desktop, and Linux. However, embracing this wide platform support introduces challenges such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handling different form factors and types: Phones, tablets, foldables, desktops, web interfaces, smartwatches, TVs, cars, smart displays, IoT, AR, VR, etc.&lt;/li&gt;
&lt;li&gt;Addressing notches, cutouts, punch holes.&lt;/li&gt;
&lt;li&gt;Scaling UI and text; ensuring accessibility.&lt;/li&gt;
&lt;li&gt;Supporting both RTL (Right-to-Left) and LTR (Left-to-Right) text directions and different type of fonts.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

❓ Do you need to support all these devices?
It's important to understand your app's requirements and the target audience before diving into responsive design. Also consider the trade-offs and the additional effort required to support each platform. But with the right approach and setup you can build apps that look great on any device.


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Setup and Key Insights
&lt;/h2&gt;

&lt;p&gt;Before diving into coding, setting up the right device and understanding key concepts are essential.&lt;/p&gt;
&lt;h3&gt;
  
  
  Recommended Emulators/Simulators or Devices
&lt;/h3&gt;

&lt;p&gt;Choose a device that you can test your app on:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Environment&lt;/th&gt;
&lt;th&gt;HotReload&lt;/th&gt;
&lt;th&gt;Resizable Window&lt;/th&gt;
&lt;th&gt;Text Scaling&lt;/th&gt;
&lt;th&gt;UI Scaling&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Windows/Mac/Linux&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Web&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android Emulator&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Experimental (only breakpoints)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iOS Simulator&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iPadOS (Stage Manager)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MacOS (Designed for iPad)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;iPad Stage Manager:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbsa2w1tczpdu7v698q1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdbsa2w1tczpdu7v698q1.png" alt="iPad Responsive"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Android Resizable Emulator:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kzxr11wspduolit7ctq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8kzxr11wspduolit7ctq.png" alt="Android Emulator"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Your App doesn't support a Platform?
&lt;/h3&gt;

&lt;p&gt;What If Your App Doesn't Support a Platform or you can not build on that platform?&lt;br&gt;
Depending on the platform you are targeting, you might not be able to build or test your app on that platform. For example, if you are developing on Windows, you won't be able to build for iOS.&lt;/p&gt;
&lt;h4&gt;
  
  
  Some alternatives:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;MacOS (Designed for iPad) or the iPadOS (Stage Manager) are great alternatives to test your iOS app as with a resizable window without building it nativly for MacOS.&lt;/li&gt;
&lt;li&gt;Use a cloud-based service like Codemagic, Bitrise, or GitHub Actions to build and test your app on different platforms.&lt;/li&gt;
&lt;li&gt;Create a version of your app that removes dependencies that are not supported on the platform you are targeting and use that version only to test the responsiveness of your app&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Foundation for Responsive Design
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Mobile First
&lt;/h3&gt;

&lt;p&gt;Starting your design with mobile in mind makes scaling up to larger screens smoother. This approach helps in efficiently adapting your designs for tablets or desktops. One popular pattern is using a Master Detail interface to adapt your screens, which we will be implementing in this guide.&lt;/p&gt;
&lt;h3&gt;
  
  
  Screen-based Breakpoints
&lt;/h3&gt;

&lt;p&gt;First things first, we establish our breakpoints. These are key in determining how our app will flex and adapt to different screen sizes. What breakpoints you should use is up to you and your usecase of the app, but here's a common example:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 dart
enum ScreenSize {
  small(300),
  normal(400),
  large(600),
  extraLarge(1200);

  final double size;

  const ScreenSize(this.size);
}

ScreenSize getScreenSize(BuildContext context) {
  double deviceWidth = MediaQuery.sizeOf(context).shortestSide;
  if (deviceWidth &amp;gt; ScreenSize.extraLarge.size) return ScreenSize.extraLarge;
  if (deviceWidth &amp;gt; ScreenSize.large.size) return ScreenSize.large;
  if (deviceWidth &amp;gt; ScreenSize.normal.size) return ScreenSize.normal;
  return ScreenSize.small;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Device Segmentation
&lt;/h3&gt;

&lt;p&gt;Categorize devices based on their form factor and type. This will help you understand the different types of devices, you need to support and how your app will adapt to them.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isMobileDevice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;kIsWeb&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isIOS&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isAndroid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isDesktopDevice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;kIsWeb&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isMacOS&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isWindows&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;Platform&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isLinux&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isMobileDeviceOrWeb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kIsWeb&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;isMobileDevice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="n"&gt;isDesktopDeviceOrWeb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;kIsWeb&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;isDesktopDevice&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Style File
&lt;/h3&gt;

&lt;p&gt;Having a style file with your app's colors, fonts, and text styles will help you maintain a consistent look and feel across your app. This will also help you in scaling your UI and text effectively when needed for different touch targets.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Layout
&lt;/h2&gt;

&lt;p&gt;We’ll be enhancing the classic Counter App to showcase responsive design in Flutter. The goal is to manage multiple counters and introduce a &lt;code&gt;master-detail&lt;/code&gt; interface for larger screens. Take a look into the repository to find out how the different topics have been implemented in detail.&lt;/p&gt;
&lt;h3&gt;
  
  
  Layout Foundation
&lt;/h3&gt;

&lt;p&gt;We create a directory &lt;code&gt;pages&lt;/code&gt; where we place all widgets which define a screen for a mobile device. Since we are using a Master-Detail design, we will define a &lt;code&gt;counters_page.dart&lt;/code&gt; and a &lt;code&gt;counter_detail_page.dart&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Building the Responsive Layout
&lt;/h3&gt;

&lt;p&gt;Now, onto the layout. We’re keeping things modular and adaptable, using &lt;a href="https://dart.dev/language/patterns" rel="noopener noreferrer"&gt;Dart Patterns&lt;/a&gt; or more specificly &lt;a href="https://dart.dev/language/patterns#switch-statements-and-expressions" rel="noopener noreferrer"&gt;Switch Expressions&lt;/a&gt; to easily switch layouts. Here’s how &lt;code&gt;app.dart&lt;/code&gt; looks:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_CounterAppState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CounterApp&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;bottomNavigationBar:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;small&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationBar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CounterDetailPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here, we’re using different navigation widgets based on the screen size — a NavigationBar for smaller screens and a NavigationRail for larger ones. Unfortunately it is a bit tricky using NavigationRail together with NavigationBar because Scaffold has only an input for a bottomNavigationBar. With the underscore we specify which layout should be shown on default.&lt;/p&gt;

&lt;p&gt;Maybe you noticed the &lt;code&gt;isPage&lt;/code&gt; flag. This flag is used for multiple purposes like to decide if the Counter Detail page should be pushed to the Navigation Stack or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adapting to Orientation Changes
&lt;/h3&gt;

&lt;p&gt;What about when users flip their phones to landscape? Using Dart’s Record feature, we can elegantly handle multiple conditions, adapting our layout to both screen size and orientation. You can react to more variables by adding them to a Record.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;_CounterAppState&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;State&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;CounterApp&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MediaQuery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orientationOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;bottomNavigationBar:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;small&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;portrait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationBar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CounterDetailPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;landscape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isPage:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Dialogs
&lt;/h3&gt;

&lt;p&gt;For a responsive UI, dialogs should adjust to screen size. In our example we want to display a fullscreen dialog on smaller screens and a dialog with dismissable background with constrained &lt;code&gt;maxWidth&lt;/code&gt; on larger screens. We can use a similar approach as we did with the layout to achieve this. Here is how:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="nl"&gt;onPressed:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;showDialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nl"&gt;context:&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Dialog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;ConstrainedBox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nl"&gt;constraints:&lt;/span&gt;
                &lt;span class="n"&gt;BoxConstraints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;maxWidth:&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;AddCounterDialog&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Dialog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fullscreen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;AddCounterDialog&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Responsive Navigation
&lt;/h3&gt;

&lt;p&gt;Consider a user navigating to the Counter Detail Screen on a small device. If the screen is resized to a larger dimension, the Counter Detail Screen remains due to direct navigation. To adapt to a larger layout, the Counter Detail Screen must be removed from the navigation stack when a resize to a bigger &lt;code&gt;ScreenSize&lt;/code&gt; is being detected. This ensures the UI remains responsive to screen resizing. We implement this behavior as follows:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;SchedulerBinding&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;instance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addPostFrameCallback&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Navigator&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;popUntil&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;route&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;isFirst&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgzdb3qkbktsu31k5836.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgzdb3qkbktsu31k5836.png" alt="Responsive Navigation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wrap the &lt;code&gt;popUntil&lt;/code&gt; method within a &lt;code&gt;SchedulerBinding.instance.addPostFrameCallback&lt;/code&gt; to delay its execution until after the current build cycle to avoiding build method conflicts.&lt;/p&gt;

&lt;h3&gt;
  
  
  Center ListView with whitespace
&lt;/h3&gt;

&lt;p&gt;On larger screens, constraining the width of scrollable lists and centering them improves aesthetics and usability. Directly wrapping a &lt;code&gt;ListView&lt;/code&gt; with a &lt;code&gt;ConstrainedBox&lt;/code&gt; may restrict scrollable area to the constrained width, excluding the white space. A workaround involves using the &lt;code&gt;padding&lt;/code&gt; parameter of &lt;code&gt;ListView&lt;/code&gt; to dynamically calculate and apply horizontal padding based on screen size:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;body:&lt;/span&gt;
 &lt;span class="n"&gt;LayoutBuilder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;builder:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;horizontalPadding&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxWidth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;
          &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;constraints&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;maxWidth&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Spacing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ListView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nl"&gt;padding:&lt;/span&gt; &lt;span class="n"&gt;EdgeInsets&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;symmetric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;horizontal:&lt;/span&gt; &lt;span class="n"&gt;horizontalPadding&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;vertical:&lt;/span&gt; &lt;span class="n"&gt;Spacing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;x3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;)}));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7ppk3jhww3rq4oxyplu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7ppk3jhww3rq4oxyplu.png" alt="Responsive List View"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach uses again the &lt;code&gt;ScreenSize&lt;/code&gt; enum to remain consistent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do we use &lt;code&gt;LayoutBuilder&lt;/code&gt; instead of &lt;code&gt;MediaQuery&lt;/code&gt;?&lt;/strong&gt;&lt;br&gt;
Since we are showing the &lt;code&gt;NavigationRail&lt;/code&gt; on larger screens, the &lt;code&gt;MediaQuery&lt;/code&gt; would ignore the constrain from the &lt;code&gt;NavigationRail&lt;/code&gt; and the &lt;code&gt;SafeArea&lt;/code&gt;. So we use &lt;code&gt;LayoutBuilder&lt;/code&gt; to get the actual constraints of the screen.&lt;br&gt;
Read more in this section: Builder vs MediaQuery&lt;/p&gt;

&lt;h2&gt;
  
  
  Widgets
&lt;/h2&gt;

&lt;p&gt;With our layout in place, it's time to explore the widgets that will enable us to construct a responsive UI. Flutter offers a rich set of widgets which are essential for creating responsive layouts and widgets. I strongly recommend reading documentation provided by the Flutter Team, which presents an extensive array of widgets in various formats. Here are some resources to get you started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Flutter Docs:&lt;/strong&gt; 

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.flutter.dev/ui/layout/responsive/building-adaptive-apps#layout-widgets" rel="noopener noreferrer"&gt;Adaptive Desgin - Layout Widgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.flutter.dev/ui/widgets/layout" rel="noopener noreferrer"&gt;Widget Catalog - Layout widgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/playlist?list=PLjxrf2q8roU2HdJQDjJzOeO6J3FoFLWr2" rel="noopener noreferrer"&gt;Youtube Flutter - Widget of the Week&lt;/a&gt; Most of them are also showcased in the Flutter Widget of the Week series.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;I will list a few important widgets that you should know when building a responsive app. Some are copied from the Flutter documentation and some are my own recommendations:&lt;/p&gt;

&lt;h3&gt;
  
  
  Single
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Align-class.html" rel="noopener noreferrer"&gt;Align&lt;/a&gt; a child within itself. It takes a double value between -1 and 1, for both the vertical and horizontal alignment.

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/AspectRatio-class.html" rel="noopener noreferrer"&gt;AspectRatio&lt;/a&gt; Attempts to size the child to a specific aspect ratio.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/ConstrainedBox-class.html" rel="noopener noreferrer"&gt;ConstrainedBox&lt;/a&gt; Imposes size constraints on its child, offering control over the minimum or maximum size.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/CustomSingleChildLayout-class.html" rel="noopener noreferrer"&gt;CustomSingleChildLayout&lt;/a&gt; Uses a delegate function to position a single child. The delegate can determine the layout constraints and positioning for the child.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Expanded-class.html" rel="noopener noreferrer"&gt;Expanded&lt;/a&gt; and &lt;a href="https://api.flutter.dev/flutter/widgets/Flexible-class.html" rel="noopener noreferrer"&gt;Flexible&lt;/a&gt; Allows a child of a Row or Column to shrink or grow to fill any available space.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/FractionallySizedBox-class.html" rel="noopener noreferrer"&gt;FractionallySizedBox&lt;/a&gt; Sizes its child to a fraction of the available space.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/LayoutBuilder-class.html" rel="noopener noreferrer"&gt;LayoutBuilder&lt;/a&gt; Builds a widget that can reflow itself based on its parents size.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html" rel="noopener noreferrer"&gt;SingleChildScrollView&lt;/a&gt; Adds scrolling to a single child. Often used with a Row or Column.
### Multi&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Column-class.html" rel="noopener noreferrer"&gt;Column&lt;/a&gt;, &lt;a href="https://api.flutter.dev/flutter/widgets/Row-class.html" rel="noopener noreferrer"&gt;Row&lt;/a&gt;, &lt;a href="https://api.flutter.dev/flutter/widgets/Flex-class.html" rel="noopener noreferrer"&gt;Flex&lt;/a&gt; Lays out children in a single horizontal or vertical run. Both Column and Row extend the Flex widget.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/CustomMultiChildLayout-class.html" rel="noopener noreferrer"&gt;CustomMultiChildLayout&lt;/a&gt;Uses a delegate function to position multiple children during the layout phase.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Flow-class.html" rel="noopener noreferrer"&gt;Flow&lt;/a&gt; Similar to CustomMultiChildLayout, but more efficient because it’s performed during the paint phase rather than the layout phase.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/ListView-class.html" rel="noopener noreferrer"&gt;ListView&lt;/a&gt;, &lt;a href="https://api.flutter.dev/flutter/widgets/GridView-class.html" rel="noopener noreferrer"&gt;GridView&lt;/a&gt; and &lt;a href="https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html" rel="noopener noreferrer"&gt;CustomScrollView&lt;/a&gt; Provides scrollable lists of children&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Stack-class.html" rel="noopener noreferrer"&gt;Stack&lt;/a&gt; Layers and positions multiple children relative to the edges of the Stack. Functions similarly to position-fixed in CSS.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Table-class.html" rel="noopener noreferrer"&gt;Table&lt;/a&gt; Uses a classic table layout algorithm for its children, combining multiple rows and columns.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Wrap-class.html" rel="noopener noreferrer"&gt;Wrap&lt;/a&gt; Displays its children in multiple horizontal or vertical runs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Slivers
&lt;/h3&gt;

&lt;p&gt;Slivers are a whole different topic, which I won't cover in this guide. But they are essential for building complex and responsive scrollable layouts. I will cover them in the future more extensively. Here are some important Sliver Widgets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/CustomScrollView-class.html" rel="noopener noreferrer"&gt;CustomScrollView&lt;/a&gt; A ScrollView that creates custom scroll effects using slivers.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/NestedScrollView-class.html" rel="noopener noreferrer"&gt;NestedScrollView&lt;/a&gt; A ScrollView that creates custom scroll effects using slivers, with a flexible header and body.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SliverCrossAxisGroup-class.html" rel="noopener noreferrer"&gt;SliverCrossAxisGroup&lt;/a&gt; A sliver that lays out multiple box children in a cross-axis group.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SliverFillRemaining-class.html" rel="noopener noreferrer"&gt;SliverFillRemaining&lt;/a&gt; A sliver that fills the remaining space in the viewport.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SliverFillViewport-class.html" rel="noopener noreferrer"&gt;SliverFillViewport&lt;/a&gt; A sliver that fills the viewport with a single box child, regardless of the child's dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SliverPadding-class.html" rel="noopener noreferrer"&gt;SliverPadding&lt;/a&gt; A sliver that adds padding to its sliver child.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/sliver_tools" rel="noopener noreferrer"&gt;sliver_tools&lt;/a&gt; A package that provides a set of sliver tools that Flutter currently lacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Extras
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SafeArea-class.html" rel="noopener noreferrer"&gt;SafeArea&lt;/a&gt; Creates a widget that avoids system intrusions.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/Spacer-class.html" rel="noopener noreferrer"&gt;Spacer&lt;/a&gt; A widget that takes up space proportional to the space between its siblings.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://api.flutter.dev/flutter/widgets/SizedBox-class.html" rel="noopener noreferrer"&gt;SizedBox&lt;/a&gt; A box with a specified size. I often use it to add space between widgets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and many more...&lt;/p&gt;

&lt;h3&gt;
  
  
  Responsive Text
&lt;/h3&gt;

&lt;p&gt;Text are often the cause for overflowing Layouts especially when using small devices. Here are some tips to make your text responsive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;overflow&lt;/code&gt; property of the Text widget to handle overflow.&lt;/li&gt;
&lt;li&gt;Wrap your Text widget with a &lt;code&gt;Flexible&lt;/code&gt; or &lt;code&gt;Expanded&lt;/code&gt; widget to make it responsive.&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;softWrap&lt;/code&gt; property to false to prevent the text from wrapping&lt;/li&gt;
&lt;li&gt;Keep in mind that many OSs have accessibility features to scale the font size dynamically so Text can easily overflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Adapting to different devices and platforms
&lt;/h2&gt;

&lt;p&gt;Building apps with Flutter allows you to use a single codebase for multiple platforms. However, adapting to the nuances of different devices and operating systems is crucial for a polished user experience. Here are some tips to ensure your app looks the same on all platforms.&lt;/p&gt;

&lt;h3&gt;
  
  
  Notches and OS System Interfaces
&lt;/h3&gt;

&lt;p&gt;Flutter's support extends to a variety of platforms, each with its own handling of notches and system interfaces. The key differences lie between Android and iOS, which we'll explore below.&lt;/p&gt;

&lt;h4&gt;
  
  
  Android
&lt;/h4&gt;

&lt;p&gt;By default, Flutter apps on Android display a black background behind the navigation pill, and when in landscape mode, a black bar appears if the phone has a notch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5w5xc72aw0sklte52e3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5w5xc72aw0sklte52e3.png" alt="Android Landscape"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To modernize the look and eliminate these black bars add following line to your root widget's &lt;code&gt;initState()&lt;/code&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

   &lt;span class="n"&gt;SystemChrome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEnabledSystemUIMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SystemUiMode&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;edgeToEdge&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This adjustment extends &lt;code&gt;ListView&lt;/code&gt; and &lt;code&gt;bottomNavigationBar&lt;/code&gt; to fill the screen, including behind the navigation pill. Avoid using SafeArea if you aim for a fully expanded view.&lt;/p&gt;

&lt;p&gt;To address the landscape mode's black bar behind the notch, modify your Android project's main styles.xml file:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;resources&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;style&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"android:windowLayoutInDisplayCutoutMode"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;shortEdges&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="c1"&gt;// ...&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;To ensure system interfaces do not obstruct your app's UI on older devices, add:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

    &lt;span class="n"&gt;SystemChrome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setSystemUIOverlayStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;SystemUiOverlayStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;statusBarColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nl"&gt;systemNavigationBarColor:&lt;/span&gt; &lt;span class="n"&gt;Colors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;));&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With these tweaks, your app will offer an uninterrupted UI experience on Android devices.&lt;/p&gt;

&lt;h4&gt;
  
  
  iOS
&lt;/h4&gt;

&lt;p&gt;iOS devices generally handle notches and system interfaces out of the box, requiring no specific alterations as mentioned for Android. However, when using iOS in landscape mode, note that padding for the notch is symmetrically applied to both sides of the screen, a design requirement by iOS that can't be easily overridden.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgw2jbcxiih6e0lhpy2kx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgw2jbcxiih6e0lhpy2kx.png" alt="iOS Landscape"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Orientation
&lt;/h3&gt;

&lt;h4&gt;
  
  
  How Orientation gets retrieved
&lt;/h4&gt;

&lt;p&gt;The orientation of the device can be determined using &lt;code&gt;MediaQuery.orientationOf(context)&lt;/code&gt;. On mobile devices equipped with a gyroscope, orientation is directly obtained. In contrast, for desktops or web platforms lacking a gyroscope, orientation is inferred from the screen dimensions: &lt;code&gt;Orientation.portrait&lt;/code&gt; if the height exceeds the width, and &lt;code&gt;Orientation.landscape&lt;/code&gt; otherwise.&lt;/p&gt;

&lt;h4&gt;
  
  
  Device Orientation
&lt;/h4&gt;

&lt;p&gt;To lock or set specific orientations for your app, include the following in your root widget's &lt;code&gt;initState&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;

 &lt;span class="n"&gt;SystemChrome&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPreferredOrientations&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="n"&gt;DeviceOrientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;portraitUp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;DeviceOrientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;portraitDown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;DeviceOrientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;landscapeLeft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;DeviceOrientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;landscapeRight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;]);&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For Apple devices, additional configuration in Xcode is required. Navigate to your project's settings under Project Runner &amp;gt; Target Runner &amp;gt; Deployment Info and select the appropriate orientation boxes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;p&gt;To effectively debug your layouts, use the Widget Inspector in DevTools. This tool allows you to thoroughly inspect each widget and its properties, understanding how it adjusts within your layout. Here are a few key features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Select Widget Mode&lt;/strong&gt;: This feature enables you to interact directly with your app's UI. Simply click on a widget in the UI, and it will be highlighted in the Inspector and the UI. It also jumps to the code, where the widget is implemented. This immediate feedback loop is invaluable for pinpointing how specific widgets are rendered and behave in your layout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Layout Explorer&lt;/strong&gt;: For an in-depth analysis, the Layout Explorer reveals how the selected widget fits into your layout. It's especially useful for visualizing and tweaking widget properties on the fly.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Widget Details Tree&lt;/strong&gt;: Dive deeper into the widget's structure with the Widget Details Tree. This view exposes the internal composition of a widget, including the widgets it utilizes internally and their respective properties.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flex Properties&lt;/strong&gt;: When selecting a Flex widget (such as a Row or Column), you have the ability to manipulate its Flex Properties and of the children. This feature lets you experiment with different property values to see real-time changes and understand how the widgets adapts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Show Guidelines&lt;/strong&gt;: Visualize the overall layout structure of your app with the Show Guidelines Button. It helps identify how widgets align with each other and where Scrollable widgets are, providing a clearer understanding of the layout's architecture.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By integrating these tools and features into your development workflow, you can significantly enhance the debugging process of your Flutter layouts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Ensuring your app delivers a consistent user experience across different screen sizes is essential. You can achieve this by conducting tests for various screen dimensions. Here’s how you can do it:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 dart
  group('Test Responsive', () {
testWidgets('should have only CountersPage', (WidgetTester tester) async {
      tester.view.devicePixelRatio = 1.0; // Not necessary but makes it easier to use the same values from our ScreenSizes
      tester.view.physicalSize =
          const Size(500, 800); // to test layout on smaller devices
      await tester.pumpWidget(const App());

      expect(find.byType(CountersPage), findsOneWidget);
      expect(find.byType(CounterDetailPage), findsNothing);
      tester.view.reset(); // Don't forget to reset view
    });

    testWidgets('should have CountersPage and Detail',
        (WidgetTester tester) async {
      tester.view.devicePixelRatio = 1.0;
      tester.view.physicalSize =
          const Size(800, 1200); // to test layout on larger devices
      await tester.pumpWidget(const App());

      expect(find.byType(CountersPage), findsOneWidget);
      expect(find.byType(CounterDetailPage), findsOneWidget);
      tester.view.reset(); // Don't forget to reset view
    });
  });


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;By default, Flutter Widget Test assumes a physicalSize of &lt;code&gt;Size(2400.0, 1800.0)&lt;/code&gt; and a devicePixelRatio of 3.0, calculating the actual display size as physicalSize / devicePixelRatio. To test layouts under different conditions, we manually adjust these values and ensure we reset the test view after each test case to avoid unintended carry-over effects. For more details on managing test window settings, refer to this &lt;a href="https://github.com/flutter/flutter/issues/100836" rel="noopener noreferrer"&gt;Flutter issue&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tips and Tricks
&lt;/h2&gt;

&lt;p&gt;Here are some tips, tricks, and misconceptions that you should keep in mind when building responsive apps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adaptive vs Responsive (Copied from &lt;a href="https://docs.flutter.dev/ui/layout/responsive/adaptive-responsive#the-difference-between-an-adaptive-and-a-responsive-app" rel="noopener noreferrer"&gt;Flutter Docs&lt;/a&gt;)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Responsive
&lt;/h4&gt;

&lt;p&gt;Typically, a responsive app has had its layout tuned for the available screen size. Often this means (for example), re-laying out the UI if the user resizes the window, or changes the device’s orientation. This is especially necessary when the same app can run on a variety of devices, from a watch, phone, tablet, to a laptop or desktop computer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Adaptive
&lt;/h4&gt;

&lt;p&gt;Adapting an app to run on different device types, such as mobile and desktop, requires dealing with mouse and keyboard input, as well as touch input. It also means there are different expectations about the app’s visual density, how component selection works (cascading menus vs bottom sheets, for example), using platform-specific features (such as top-level windows), and more.&lt;/p&gt;

&lt;p&gt;There is a great article how Google achieved this with Google Earth from Craig Labenz about adaptive Design: &lt;a href="https://medium.com/flutter/extreme-ui-adaptability-in-flutter-how-google-earth-supports-every-use-case-on-earth-6db4661e7a17" rel="noopener noreferrer"&gt;How Google Earth supports every use case on earth&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Helpful Libraries
&lt;/h3&gt;

&lt;p&gt;Here are some libraries that can help you build responsive apps. I couldn't try them out yet extensively, but they look promising:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/flutter_adaptive_scaffold" rel="noopener noreferrer"&gt;flutter_adaptive_scaffold&lt;/a&gt;: A Flutter package that provides adaptive/responsive scaffold widgets for different platforms.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/device_preview" rel="noopener noreferrer"&gt;device_preview&lt;/a&gt;: A Flutter package that allows you to preview your app on different devices and test your responsive UI.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://pub.dev/packages/wolt_modal_sheet" rel="noopener noreferrer"&gt;wolt_modal_sheet&lt;/a&gt;: A Flutter package that provides a responsive modal sheet widget.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Use a State Management Library
&lt;/h3&gt;

&lt;p&gt;Using a state management library like Riverpod, Provider, or Bloc will help you manage your app's state effectively when the app is being resized. This will help you in managing your app's state across different screen sizes and devices. It will also help you in testing your app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Design a Prototype first
&lt;/h3&gt;

&lt;p&gt;Using Tools like Figma can help you in designing your app for different screen sizes and devices. It will also help you in understanding how your app will look on different devices. Iterating on your design will help you and save you a lot of time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hardcoded Sizes and Values
&lt;/h3&gt;

&lt;p&gt;Avoid relying on hardcoded sizes and values within your app, as they frequently lead to UI overflow issues. If the use of hardcoded values is unavoidable, ensure that your widgets, such as &lt;code&gt;Text&lt;/code&gt; widgets, can overflow rightfully. Refer to the dedicated section in this guide for more details on managing overflow with &lt;code&gt;Text&lt;/code&gt; widgets.&lt;/p&gt;

&lt;p&gt;Additionally, consider utilizing ConstrainedBox to introduce a degree of flexibility to your widgets. This approach allows you to set minimum and maximum constraints, providing your layout with the adaptability it needs to accommodate different screen sizes and orientations without compromising on design integrity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Builder vs MediaQuery
&lt;/h3&gt;

&lt;p&gt;⚠️&lt;strong&gt;Warning&lt;/strong&gt; &lt;code&gt;MediaQuery&lt;/code&gt; should be used with caution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;MediaQuery&lt;/code&gt; comes with different methods like &lt;code&gt;sizeOf&lt;/code&gt; or &lt;code&gt;orientationOf&lt;/code&gt; which you should use instead of &lt;code&gt;MediaQuery.of(context).size&lt;/code&gt; or &lt;code&gt;MediaQuery.of(context).orientation&lt;/code&gt;. The reason is you only want rebuilds whenever that specific property changes.&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;MediaQuery&lt;/code&gt; can have unwanted rebuilds. So make sure to only use it in the very top of your Widget Tree to define the whole Layout.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;MediaQuery&lt;/code&gt; ignores paddings, SafeArea and other constraints because you get the size of the app window itself&lt;/li&gt;
&lt;li&gt;For child widgets you should use &lt;code&gt;LayoutBuilder&lt;/code&gt; or &lt;code&gt;OrientationBuilder&lt;/code&gt; to get the actual constraints for the widget&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Why not just use &lt;code&gt;LayoutBuilder&lt;/code&gt; and &lt;code&gt;OrientationBuilder&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Using &lt;code&gt;LayoutBuilder&lt;/code&gt; and &lt;code&gt;OrientationBuilder&lt;/code&gt; can sometimes get a bit hacky to use especially when using them in combination for complex layouts. For that reason I prefer to use &lt;code&gt;MediaQuery&lt;/code&gt;. But you could use &lt;code&gt;LayoutBuilder&lt;/code&gt; and &lt;code&gt;OrientationBuilder&lt;/code&gt; to get the same results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Our app now dynamically responds to every screen size. The beauty of Flutter is that it provides all the tools necessary for responsive design across any device.&lt;/p&gt;

&lt;p&gt;Keen to see these methods in action? Check out my app, &lt;strong&gt;Yawa: Weather &amp;amp; Radar&lt;/strong&gt;, on &lt;a href="https://play.google.com/store/apps/details?id=de.digregorio.dario.yawa" rel="noopener noreferrer"&gt;Android&lt;/a&gt; and &lt;a href="https://apps.apple.com/de/app/yawa-weather-forecast/id1626828365" rel="noopener noreferrer"&gt;iOS&lt;/a&gt; and if you like my App Yawa, please leave a review. This would help me a lot :) ❤️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ypw54xa16oohgzptug5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ypw54xa16oohgzptug5.png" alt="Yawa"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, feel free to reach out on &lt;a href="https://twitter.com/digregoriodario" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>responsive</category>
      <category>flutter</category>
      <category>ui</category>
      <category>ux</category>
    </item>
    <item>
      <title>Building Responsive UIs in Flutter: A Short Guide</title>
      <dc:creator>Dario Digregorio</dc:creator>
      <pubDate>Wed, 15 Nov 2023 20:53:10 +0000</pubDate>
      <link>https://dev.to/dariodigregorio/building-responsive-uis-in-flutter-a-short-guide-5871</link>
      <guid>https://dev.to/dariodigregorio/building-responsive-uis-in-flutter-a-short-guide-5871</guid>
      <description>&lt;p&gt;Flutter has become a go-to framework for developing cross-platform apps, but the real challenge lies in making these apps responsive across a variety of devices. This article is all about navigating the world of Flutter to ensure your app looks and works great, whether on mobile, desktop, or web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side Note&lt;/strong&gt;: This guide sticks to the basics of Flutter for responsiveness, avoiding additional packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Tools I’m Using:&lt;/strong&gt; For this, I’m working with Dart 3.1.3, Flutter 3.13.9 and optional Riverpod 2.4.5.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting Up and Key Insights
&lt;/h1&gt;

&lt;p&gt;Testing your layouts on different devices and platforms is crucial. Choose a development environment that allows easy resizing. Each platform has its nuances, so let’s explore them:&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Platform and Device Differences
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Windows/MacOS/Web:&lt;/strong&gt; These are the easiest for development. They offer flexible window resizing and support HotReload. However, Flutter Web doesn’t support HotReload. Also, &lt;code&gt;MediaQuery.orientationOf()&lt;/code&gt; here is based on window size, not device orientation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MacOS Í(Designed for iPad):&lt;/strong&gt; Optimize your app for both iOS and MacOS with the ‘My Mac (Designed for iPad)’ target in Xcode. This special build allows you to create an iOS-optimized app that functions seamlessly on MacOS. It behaves like a native MacOS app while maintaining compatibility with libraries used in the iOS version. This approach offers a unified development process for both platforms, ensuring that your app delivers a consistent experience across Apple devices. There is still some work to set it up properly. See this &lt;a href="https://github.com/flutter/flutter/issues/125741" rel="noopener noreferrer"&gt;issue&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iPad with Stage Manager:&lt;/strong&gt; If your dependencies limit your platform choice, an iPad with Stage Manager is a good option. It allows resizing within predefined screen sizes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafphwm7d1hr648n3rilc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafphwm7d1hr648n3rilc.png" alt="Resizable Experimental Emulator Menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Android:&lt;/strong&gt; The Android Resizable Emulator, still in its experimental phase, lets you switch between phone, foldable, or tablet modes. It’s a bit buggy, but useful. Android’s split-screen feature is also worth exploring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1v0avg3cpp9wxuy50e6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1v0avg3cpp9wxuy50e6.png" alt="Resizable Experimental Emulator Menu"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;iOS:&lt;/strong&gt; iOS is more restrictive, lacking a split-screen feature and offering limited screen sizes. The presence of the notch on modern iPhones adds to the responsiveness challenge, especially with the behavior of &lt;code&gt;SafeArea&lt;/code&gt;. iOS adds an additional Padding to the other side of the Notch. Read more in this &lt;a href="https://github.com/flutter/flutter/issues/28956#issuecomment-472188242" rel="noopener noreferrer"&gt;issue&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mobile-First Approach
&lt;/h2&gt;

&lt;p&gt;Starting your design with mobile in mind makes scaling up to larger screens smoother. This approach helps in efficiently adapting your designs for tablets or desktops. One popular pattern is using a &lt;a href="https://en.wikipedia.org/wiki/Master%E2%80%93detail_interface" rel="noopener noreferrer"&gt;Master Detail interface&lt;/a&gt; to adapt your screens.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fonts
&lt;/h2&gt;

&lt;p&gt;Pay attention to font sizes and language directions (LTR vs. RTL). These can mess up your layout so make sure to test your layouts properly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Composite Pattern
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Composite_pattern" rel="noopener noreferrer"&gt;Composite Pattern&lt;/a&gt; is effective for organizing widgets, making it easier to reuse and adjust your code. While I’m using Riverpod for state management, you can choose any library that suits your project. This pattern also aids in adapting widgets inside your layouts to different screen sizes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementation: Bringing It All Together
&lt;/h1&gt;

&lt;p&gt;Now, let’s dive into the practical side of things. We’ll be enhancing the classic Counter App to showcase responsive design in Flutter. The goal is to manage multiple counters and introduce a master-detail interface for larger screens.&lt;/p&gt;

&lt;p&gt;REPOSITORY: &lt;a href="https://github.com/dario-digregorio/flutter_responsive" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqeaak4qbkem4sfaatsq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxqeaak4qbkem4sfaatsq.png" alt="1. Counters Page, 2. Counter Detail Page, 3. Master Detail for bigger Screens"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Breakpoints: The Foundation
&lt;/h2&gt;

&lt;p&gt;First things first, we establish our breakpoints. These are key in determining how our app will flex and adapt to different screen sizes. Let’s take a look at our foundation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kt"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;small&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;large&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;extraLarge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;ScreenSize&lt;/span&gt; &lt;span class="nf"&gt;getScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;deviceWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MediaQuery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;sizeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;shortestSide&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Gives us the shortest side of the device&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deviceWidth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;extraLarge&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deviceWidth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deviceWidth&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;normal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;small&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup uses enums to categorize screen sizes, making it easier for us to tailor the app’s layout to the device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building the Responsive Layout
&lt;/h2&gt;

&lt;p&gt;Now, onto the layout. We’re keeping things modular and adaptable, using &lt;a href="https://dart.dev/language/patterns" rel="noopener noreferrer"&gt;Dart Patterns&lt;/a&gt; to easily switch layouts. Here’s how our main widget shapes up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterAppContent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterAppContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;bottomNavigationBar:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// For larger screens, we might not need a bottom nav&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationBar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="c1"&gt;// The standard bottom nav&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;SafeArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// A layout for larger screens&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isFullPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// isFullPage is being used to define if the CounterTiles should navigate&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CounterDetailPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="c1"&gt;// The default layout for smaller screens&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we’re using different navigation widgets based on the screen size — a &lt;code&gt;NavigationBar&lt;/code&gt; for smaller screens and a &lt;code&gt;NavigationRail&lt;/code&gt; for larger ones. Unfortunately it is a bit tricky using &lt;code&gt;NavigationRail&lt;/code&gt; together with &lt;code&gt;NavigationBar&lt;/code&gt; because &lt;code&gt;Scaffold&lt;/code&gt; has only an input for a &lt;code&gt;bottomNavigationBar&lt;/code&gt;. With the underscore we specify which layout should be shown on default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adapting to Orientation Changes
&lt;/h2&gt;

&lt;p&gt;What about when users flip their phones to landscape? We’ve got that covered too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CounterAppContent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="n"&gt;StatelessWidget&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterAppContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nd"&gt;@override&lt;/span&gt;
  &lt;span class="n"&gt;Widget&lt;/span&gt; &lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BuildContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;screenSize&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;getScreenSize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MediaQuery&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orientationOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Scaffold&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nl"&gt;bottomNavigationBar:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;landscape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// we will show NavigationRail when ever the app is being used in landscape&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CounterNavigationBar&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nl"&gt;body:&lt;/span&gt; &lt;span class="n"&gt;SafeArea&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;screenSize&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ScreenSize&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;isFullPage:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CounterDetailPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Orientation&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;landscape&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;Row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="c1"&gt;// the same here&lt;/span&gt;
              &lt;span class="nl"&gt;children:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="n"&gt;CounterNavigationRail&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="n"&gt;VerticalDivider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nl"&gt;thickness:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nl"&gt;width:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;Expanded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                  &lt;span class="nl"&gt;child:&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;
              &lt;span class="p"&gt;],&lt;/span&gt;
            &lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="n"&gt;CountersPage&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Dart’s Record feature, we can elegantly handle multiple conditions, adapting our layout to both screen size and orientation. You can react to more variables by adding them to the Record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry3asw1tz6wxozo86le0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry3asw1tz6wxozo86le0.png" alt="Counter App resizes to different Layouts&amp;lt;br&amp;gt;
"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Our app now dynamically responds to every screen size. The beauty of Flutter is that it provides all the tools necessary for responsive design across any device. Don’t forget to check the source code on &lt;a href="https://github.com/dario-digregorio/flutter_responsive" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; for more insights.&lt;/p&gt;

&lt;p&gt;Keen to see these methods in action? Check out my app, Yawa: Weather &amp;amp; Radar, on &lt;a href="https://play.google.com/store/apps/details?id=de.digregorio.dario.yawa" rel="noopener noreferrer"&gt;Android&lt;/a&gt; and &lt;a href="https://apps.apple.com/de/app/yawa-weather-forecast/id1626828365" rel="noopener noreferrer"&gt;iOS&lt;/a&gt;. And if you have any questions or feedback, feel free to reach out on &lt;a href="https://twitter.com/DigregorioDario" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;!&lt;/p&gt;

</description>
      <category>flutter</category>
      <category>dart</category>
      <category>ui</category>
      <category>design</category>
    </item>
  </channel>
</rss>
