skip to Main Content

I have been trying to make my app’s fontsize responsive so that it can vary based on device size.

I tried to use Media Query to do that, specifically these lines of code below but they do not seem work based on the screenshots below where on one screen the text is lined up on one line and the other, the text is on 2 lines.
The lines of code:

MediaQueryData mediaQueryData = MediaQuery.of(context);
screenWidth = _mediaQueryData.size.width;
screenHeight = _mediaQueryData.size.height;
double safeAreaWidth = _mediaQueryData.padding.left + _mediaQueryData.padding.right;
double safeAreaHeight = _mediaQueryData.padding.top + _mediaQueryData.padding.bottom;
safeWidth = (screenWidth - safeAreaWidth);
safeHeight = (screenHeight - safeAreaHeight);

//Scale factor for responsive UI
scaleFactorHeight = (safeHeight / 820);
if (scaleFactorHeight < 1) {
   double diff = (1 - scaleFactorHeight) * (1 - scaleFactorHeight);
   scaleFactorHeight += diff;
}
scaleFactorWidth = safeWidth / 392;
if (scaleFactorWidth < 1) {
   double diff = (1 - scaleFactorWidth) * (1 - scaleFactorWidth);
   scaleFactorWidth += diff;
}

The screenshots of the 2 images:

enter image description here enter image description here

3

Answers


  1. import 'dart:ui' as ui;
    
    import 'package:fluid_app/presentation/constant/constans.dart';
    
    class ResponsiveUtils { ResponsiveUtils._internal();
    
    static ResponsiveUtils? _instance;
    
    factory ResponsiveUtils() { _instance ??= ResponsiveUtils._internal(); return _instance!; }
    
    late double devicePixelRatio;
    
    late double deviceWidth; late double deviceHeight;
    
    static const prototypeWidth = relativeWidth; static const prototypeHeight = relativeHeight;
    
    late double heightFactor; late double widthFactor;
    
    late double safeAreaTop; late double safeAreaBottom;
    
    void init() { devicePixelRatio = ui.window.devicePixelRatio; deviceWidth = ui.window.physicalSize.width / devicePixelRatio; deviceHeight = ui.window.physicalSize.height / devicePixelRatio; heightFactor = deviceHeight / prototypeHeight; widthFactor = deviceWidth / prototypeWidth; safeAreaTop = ui.window.padding.top / devicePixelRatio; safeAreaBottom = ui.window.padding.bottom / devicePixelRatio; } }
    
    extension ResponsiveHelperDouble on double { double get awr { final value = this * ResponsiveUtils().widthFactor; if (this == 0) { return 0; } if (value == 0) { ResponsiveUtils().init(); return this; } return value; }
    
    double get ahr { final value = this * ResponsiveUtils().heightFactor; if (this == 0) { return 0; } if (value == 0) { ResponsiveUtils().init(); return this; } return value; } }
    
    extension ResponsiveHelperInt on int { double get awr { final value = this * ResponsiveUtils().widthFactor; if (this == 0) { return 0; } if (value == 0) { ResponsiveUtils().init(); return toDouble(); } return value; }
    
    double get ahr { final value = this * ResponsiveUtils().heightFactor; if (this == 0) { return 0; } if (value == 0) { ResponsiveUtils().init(); return toDouble(); } return value; } }
    
    class MyApp extends StatelessWidget { @override Widget build(BuildContext context){ ResponsiveUtils().init(); return ...
    
    } }
    
    
    
     class SomePage extends StatelessWidget{ @override Widget build(BuildContext context){
        
        return Center(child: Text('hello', style : TextStyle(fontSize: 12.awr)));
        
        } }
    
    Login or Signup to reply.
  2. Generally, any scaling that is driven by device width is wrong. TL;DR: use LayoutBuilder (not MediaQuery) to determine breakpoints only (side nav vs bottom nav, two columns vs three). Then use Flex widgets (Row, Column, Expanded, Spacer, etc) to lay out your text. Do not change the font size.

    The way to remember this is to think back to the last time you made a web page or a desktop app wider. Did the characters get bigger? No? 🙂 Then stop making your apps "scale" font sizes. Use width to re-layout, not re-size.

    Login or Signup to reply.
  3. Just wrap the desired widget (if you want it to work in the whole app – do it at the top of the widget tree) in a MediaQuery widget and overwrite the textScaleFactor in accordance with your desired logic.

    import 'package:flutter/widgets.dart';
    
    class FontScaleWrapper extends StatelessWidget {
      const FontScaleWrapper({super.key, required this.child});
    
      final Widget child;
    
      @override
      Widget build(BuildContext context) {
        return MediaQuery(
          data: MediaQuery.of(context).copyWith(
            textScaleFactor: ///Add the font size logic here!,
          ),
          child: child,
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search