How to manage global textScaleFactor in Flutter app properly?

5,571

Solution 1

This solution was presented during Google I/O'19 (around the 20-minute mark):

MaterialApp(
  builder: (BuildContext context, Widget child){
    final MediaQueryData data = MediaQuery.of(context);
    return MediaQuery(
      data: data.copyWith(
        textScaleFactor: data.textScaleFactor * (_isPassive ? 2 : 1)
      ),
      child: child,
    );
  },

If you wish that everything had a fixed textScaleFactor, you could replace data.textScaleFactor * (_isPassive ? 2 : 1) for a single number. 1.0 would make your design to always follow your fontSizes.

Solution 2

You can set a limit after which you don't need to scale, as some apple apps do.

MaterialApp(
  builder: (BuildContext context, Widget child) {
    final MediaQueryData data = MediaQuery.of(context);
    return MediaQuery(
      data: data.copyWith(
        textScaleFactor: data.textScaleFactor > 2.0 ? 2.0 : data.textScaleFactor),
        child: child,
       );
    },
  debugShowCheckedModeBanner: false,
  title: 'Flutter app',
)

In addition, I added 2 functions that calculate the size for different cases.

  1. Always returns a fixed text size, for any textScaleFactor:
double getFixedSize(double textSize) {
  return textScaleFactor != 1.0 ? textSize / textScaleFactor : textSize;
}

For example, you can use it for app title text.

  1. Returns scaled textSize until specific scale is not reached, which is set by the second maxScaleFactor parameter:
double getScaledOrMaxSize(double textSize, double maxScaleFactor) {
 return textScaleFactor > maxScaleFactor
   ? textSize * maxScaleFactor / textScaleFactor
   : textSize;
}

This can be used for example for headers that are already large and you don't need to increase them even more.

I hope this helps you make good apps for visually impaired people while still leaving them beautiful.

Solution 3

To limit the textScaleFactor for ALL PAGES in your app, you can do this.

Wrap your MaterialApp with a MediaQuery widget with the desired MediaQueryData data which is created from the window.

And set useInheritedMediaQuery to true.

@override
Widget build(BuildContext context) {
  MediaQueryData windowData =
      MediaQueryData.fromWindow(WidgetsBinding.instance!.window);
  windowData = windowData.copyWith(
    textScaleFactor:
        windowData.textScaleFactor > 1.4 ? 1.4 : windowData.textScaleFactor,
  );
  return MediaQuery(
    data: windowData,
    child: MaterialApp(
      useInheritedMediaQuery: true,

      //...
    ),
  );
}

Share:
5,571
moonvader
Author by

moonvader

web, dev, Wordpress, Arduino, iOS, Flutter, Mobile

Updated on December 11, 2022

Comments

  • moonvader
    moonvader over 1 year

    Flutter apps react on system large text making all Text widgets really large. I want to limit textScaleFactor for Text widgets but I want to do it globally not in each Text widget that I'am using.

    Now after enabling large text I got exceptions like

    flutter: ══╡ EXCEPTION CAUGHT BY RENDERING LIBRARY ╞═════════════════════════════════════════════════════════ flutter: The following message was thrown during layout: flutter: A RenderFlex overflowed by 14 pixels on the bottom.

    What is proper way to do it? One way is to create some wrapper widget instead of using Text, but maybe it can be solved other way?

    image 1 image 2

  • Volodymyr Bilovus
    Volodymyr Bilovus over 4 years
    _isPassive - what do they store in this variable?
  • moonvader
    moonvader over 4 years
    youtube.com/watch?v=YSULAJf6R6M 20:00 they talk about passive way of interacting with content (ex: TV)
  • Alexandru Rusu
    Alexandru Rusu about 3 years
    Is there a method to set this globally for all pages? As far as I can see this method ensures the textScaleFactor only for the widget tree of that screen/page.
  • Hillel Coren
    Hillel Coren over 2 years
    Just want to note to be careful setting useInheritedMediaQuery to true. In our app it caused problems in determining the height of the screen when the keyboard is shown.
  • vkammerer
    vkammerer about 2 years
    "as some apple apps do". Could you let me know which apple apps do not scale past a certain threshold?
  • Andrew Nodermann
    Andrew Nodermann about 2 years
    You can open standard iPhone apps and continue to scale the font in the iPhone settings, comparing it with the app on flutter, you will see the difference.