Managing Global textScaleFactor in Flutter

I have to admit, I was missing something very important as a perspective of user experience. I was missing the Accessibility feature of our operating system while developing a production application. We all know that our OS gives us the ability to increase or decrease the font size as per the user convenience but are we using it to test our applications?

If you have published the application or in production lets follow the below steps for a good test on your mobile phone:

iOS : System Settings -> Accessibility -> Display and Text Size -> Large Text -> Turn on Larger Accessibility Sizes
Android : System Settings -> Accessibility -> Font Size

Now, step back into your Flutter application!!

Already Surprised, if your application is overflowing pixels everywhere….

If you have to take care of the responsiveness of the Flutter application, then you are safe but for those who have missed it, it's a big deal.

“textScaleFactor in Flutter is the Saviour”

MediaQuery.of(context).textScaleFactor

textScaleFactor tells you by how much text output in the app should be scaled. Users can change this in their mobile phone/device settings

Note: By default, the textScaleFactor is 1.0 if the font size of the mobile phone is normal and increases or decreases as per the font size set in the mobile phone.

Recommendations: Instead of using hardcoded text sizes, you should use theme-based text size and keep your UI flexible enough to adjust on different screen sizes and font sizes set by the system. There are more things to consider when developing a production app but this is the place to get those techniques.

If your application is not supporting the responsiveness of each widget used, then here are few approaches:

Approach 1: Make your application expand its font size according to the passive display as most of the apps consider it in Material Theming (Recommended)

User passive way of interacting in content:

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 it's a passive display, increase the font size for a better user experience or else let the application use its normal font size.

Approach 2: Make your application expand its font size according to the threshold or limit you specify as many other iOS / Android 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,
);
},
title: 'Flutter app',
)

If the user didn't change anything in the settings (because textScaleFactor by default is 1). But if changes were made, the font size of this text respects the user settings until it has a value ≤2. If the value exceeds the threshold then it will keep the maximum scale size of 2. If the font size is decreased, it application’s font size will decrease its size accordingly.

Approach 3: Fix the font size of the complete Application throughout.

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

Setting textScaleFactor to 1.0, will keep the font Size exactly the same fixed in the application and will not increase or decrease according to the mobile phone’s font size.

After following these approaches once again test your application.

Apart from this, we can set the title and content font according to textScaleFactor dynamically.

  1. If you want to return a fixed text size for your application:
double getFixedSize(double textSize) {
return textScaleFactor != 1.0 ? textSize / textScaleFactor : textSize;
}

You can use it for app title text.

  1. Returns scaled textSize until a 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. Also, an application that is compatible with the mobile accessibility feature. :)

Did I get something wrong? Mention it in the comments. I would love to improve.

If you learned even a thing or two, clap your hands 👏 as many times as you can to show your support! This motivates me to write more.

“Flutter high with Flutter” 🙌🏼

Hint Source — stackoverflow, pub.dev

Senior Software Engineer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store