skip to Main Content

I’m switching from a third party tool that I made a template for to Flutter to become independent from that third party tool.

I have a lot of icons, some syncfusion gauges and texts on my screen and I’ve now come to the point where for the first part all elements are there and at a position where I’m happy with when testing inside a Google Pixel emulator.

I have then realized that when trying it on a physical tablet or testing it in a browser and resizing the window, things start moving weirdly (kinda expected of course)

I tried implementing dynamic resizing with some help from ChatGPT and it ended up using a lot of wrapping in SizedBoxes, Flexibles and Containers together with screen size calculations that were kinda painful to make especially because every damn element needs a different factor which ended up looking like this for size calculations:

double screenWidth = constraints.maxWidth;
double screenHeight = constraints.maxHeight;

double factor = 15;

double areaFactor = screenWidth * screenHeight / 1000000;

double fontSizeCenterLarge = areaFactor * 35;
double fontSizeCenterMedium = areaFactor * 25;
double fontSizeCenterSmall = areaFactor * 12;

double gaugeCenterSize = areaFactor * factor;
double gaugeIconSize = gaugeCenterSize * 2;
double fontSizeGaugeLarge = areaFactor * factor;
double fontSizeGaugeMedium = areaFactor * factor;
double fontSizeGaugeSmall = areaFactor * factor;
double gaugeLabelOffsetLarge = areaFactor * factor;
double gaugeLabelOffsetMedium = areaFactor * factor;
double gaugeLabelOffsetSmall = areaFactor * factor;

An element for example would have looked like this then:

Container(
  width: gaugeCenterSize * 9.2,
  height: gaugeCenterSize * 9.2,
  decoration: const BoxDecoration(
    shape: BoxShape.circle,
    gradient: LinearGradient(
      begin: Alignment.bottomCenter,
      end: Alignment.topCenter,
      colors: [
        Colors.black87,
        Colors.white30
      ],
      stops: [0.0, 1.0],
    ),
  ),
),

this:

SizedBox(
  width: gaugeIconSize,
  height: gaugeIconSize,
  child: Image.asset(
  ccEngaged
    ? 'assets/images/ccon.png'
    : 'assets/images/ccoff.png',
  fit: BoxFit.contain,
  ),
),

or like this:

Flexible(
  fit: FlexFit.loose,
  child: FittedBox(
    fit: BoxFit.scaleDown,
    child: Text(
      gear.toString(),
      style: TextStyle(
        fontSize: fontSizeCenterMedium,
        color: Colors.white,
        fontFamily: 'Prime',
      ),
      maxLines: 1,
      overflow: TextOverflow.ellipsis,
    ),
  ),
),

I figured these would then resize the elements proportionally to the screen size, but they didn’t, they even shifted around in some cases and texts started clipping into invisible borders. I’d really like things to move and resize properly and proportionally on any platform since this is planned to be used on desktop/web and mobile.

It also feels like there would be a simpler way or something that gives more control over how things actually behave when resized, that I don’t know about (yet)

3

Answers


  1. you can use flutter_screenutils instead, it is perfect.

    Login or Signup to reply.
  2. For dynamic resizing based on the screen sizes in flutter here are a few approaches that might help simplify and improve your solution:

    1. Use MediaQuery for Dynamic Screen Size Calculation
    2. Responsive Layouts Using LayoutBuilder
    3. Flexible Widgets and FittedBox for Scaling
    4. Using flutter_screenutil for Proportional Scaling
    5. Using FractionallySizedBox for Flexible Resizing

    MediaQuery for Dynamic Screen Size Calculation

    Use MediaQuery to obtain the current screen’s width, height, and device pixel ratio. This way, you can ensure that the layout scales dynamically based on the actual device screen size.

    For Example:

    double screenWidth = MediaQuery.of(context).size.width;
    double screenHeight = MediaQuery.of(context).size.height;
    double devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
    
    double factor = screenWidth / 375; // 375 is a reference width (e.g., iPhone 6)
    
    double fontSize = factor * 16; // Adjust font size dynamically
    double iconSize = factor * 24; // Adjust icon size dynamically
    

    With this approach you can easily scale your UI for different screen sizes.

    for further details: MediaQuery

    Responsive Layouts Using LayoutBuilder

    Layout builder provides you the dimensions of the parent widget, then using those dimensions to scale the child widgets.

    Forexample:

    LayoutBuilder(
      builder: (context, constraints) {
        double screenWidth = constraints.maxWidth;
        double screenHeight = constraints.maxHeight;
        double factor = screenWidth / 375;
    
        return Column(
          children: [
            Container(
              width: screenWidth * 0.5,
              height: screenHeight * 0.2,
              color: Colors.blue,
              child: Text(
                'Responsive Container',
                style: TextStyle(fontSize: factor * 20),
              ),
            ),
            Icon(
              Icons.access_alarm,
              size: factor * 40,
            ),
          ],
        );
      },
    );
    

    now the child widgets will adjust automatically on different screen sizes.

    for further details on LayoutBuilder.

    Flexible Widgets and FittedBox for Scaling

    Using Flexible and FittedBox will make sure the widgets resize proportionally without providing the size manually.
    Flexible widget adjusts the widget elements based on the available space, while FittedBox make sure that the content fits with in the available bounds.

    ForExample:

    Flexible(
      child: FittedBox(
        fit: BoxFit.scaleDown,
        child: Text(
          'Responsive Text',
          style: TextStyle(
            fontSize: 18,
            color: Colors.black,
          ),
        ),
      ),
    )
    

    Now the FittedBox will automatically scales the content within the available space.

    For further details on Flexible.
    For further details on FittedBox.

    flutter_screenutil for Proportional Scaling

    flutter_screenutil provides an easy way to define the widget size ratios that scale proportionally to the screen’s dimensions.

    for example:

    Container(
      width: 200.w,  // Scales width proportionally
      height: 100.h,  // Scales height proportionally
      child: Text(
        'Responsive Text',
        style: TextStyle(fontSize: 20.sp),  // Scales font size proportionally
      ),
    ) 
    

    for further details visit this page: flutter_screenutils

    FractionallySizedBox for Flexible Resizing

    FractionallySizedBox ensures that the element’s size is proportional to the parent widget size by defining the width and height proportional to the parent’s size.

    For Example:

    FractionallySizedBox(
      widthFactor: 0.8, // 80% of the parent width
      heightFactor: 0.3, // 30% of the parent height
      child: Container(
        color: Colors.green,
        child: Text('I resize with the parent'),
      ),
    )
    

    for further details: FractionallySizedBox

    Login or Signup to reply.
  3. You don’t want pixel perfect. You want responsive. And Flutter has many amazing tools to make responsive layouts, like LayoutBuilder for breakpoints, and Flex (Row/Column) widgets for adaptive sizing. Figma and other mockup tools are generally very poor at representing this… the best tool to preview layout designs is Flutter itself (thanks to hot reload). Oh, and familiarize yourself with less-referenced layout widgets like FittedBox, FractionallySizedBox, AspectRatio, Spacer, Wrap, and learn when to use double.infinity for a width or height rather than querying with MediaQuery for the useless screen size. This is a great writeup from the author of Boxy on the fundamentals of Flutter layout including MediaQuery: https://notes.tst.sh/flutter/media-query/.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search