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
you can use flutter_screenutils instead, it is perfect.
For dynamic resizing based on the screen sizes in flutter here are a few approaches that might help simplify and improve your solution:
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:
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:
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:
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:
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:
for further details: FractionallySizedBox
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/.