How to manage global textScaleFactor in Flutter app properly?
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 fontSize
s.
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.
- 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.
- 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,
//...
),
);
}
Comments
-
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?
-
Volodymyr Bilovus over 4 years_isPassive - what do they store in this variable?
-
moonvader over 4 yearsyoutube.com/watch?v=YSULAJf6R6M 20:00 they talk about passive way of interacting with content (ex: TV)
-
Alexandru Rusu about 3 yearsIs 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 over 2 yearsJust 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 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 about 2 yearsYou 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.