Text Scaling in Flutter

Akshat kaneria
Flutter Clan
Published in
3 min readJun 30, 2021
Photo by Markus Winkler on Unsplash

Introduction:

Sometimes people prefer reading enlarged text on their phones rather than the usual size or they would like to customise the size of the text, so if your app contains a lot of reading material then text scaling would be a really nice feature to have in your app. In this way, the users can customise the font size according to their needs. In this post, we’ll be discussing about how to implement text scaling in your Flutter app.

Getting Started:

I have created a simple Flutter app to demonstrate the working of text scaling. The app consists of a single screen where there are multiple texts with different font sizes. There is a slider at the bottom of the screen which can be used to change the text scale factor. As the slider moves, the change in the size of all the texts is reflected on the screen.

The working of the app is shown below:

Implementation:

Now, let’s dive into the implementation part. We’ll be using an InheritedWidget for implementing our text scaler. Inherited widget is used to pass data from an ancestor widget to descendant ones, which are possibly deep down the widget tree. I would recommended you to learn more about InheritedWidget and how to use it before proceeding with this article.

First of all, I have created a TextScalingFactor class which contains a scaleFactor value. This will be passed using our InheritedWidget and then it can be used with all the Text widgets in our app.

The implementation is as below:

Here, “==” operator has been overridden to add more checks for comparing two objects of TextScalingFactor.

Now, let’s create our TextScaler class. The implementation of which is as below:

Let’s analyse this file now.

Here, we have used <T> in all the classes as we want the classes to be generic. _ScalingFactorBindingScope class is extending InheritedWidget and it contains scalingFactorBindingState which is a state of TextScaler i.e. _TextScalerState. Also, updateShouldNotify defines whether the framework should notify widgets that inherit from this widget and thus we return true as we need to rebuild the widgets that inherit from this widget (InheritedWidget).

TextScaler is our main widget which will be wrapped at the root level. It is a StatefulWidget as we need to change the state of this widget as soon as the value of TextScalingFactor changes. initialScaleFactor will define the initial scaling factor. _ScalingFactorBindingScope is being used inside TextScaler as shown below:

@override
Widget build(BuildContext context) {
return _ScalingFactorBindingScope<T>(
scalingFactorBindingState: this,
child: widget.child,
);
}

The of method defined in TextScaler will be used to access the current value that is being passed using the InheritedWidget i.e. currentValue of _TextScalerState. The implementation of which is as below:

static T of<T>(BuildContext context) {
final _ScalingFactorBindingScope<T> scope = context.dependOnInheritedWidgetOfExactType<_ScalingFactorBindingScope<T>>();
return scope?.scalingFactorBindingState?.currentValue;
}

The update method will be used to updated the value that is being passed using the InheritedWidget. Here, update method is internally calling updateModel method of _TextScalerState. The implementation is as below:

static void update<T>(BuildContext context, T newModel) {
final _ScalingFactorBindingScope<dynamic> scope = context.dependOnInheritedWidgetOfExactType<_ScalingFactorBindingScope<T>>();
scope?.scalingFactorBindingState?.updateModel(newModel);
}

Now, we’re all set. Here’s how we can wrap TextScaler at the root of our application and pass an initial scaling factor which is TextScalingFactor(scaleFactor: 1.25) in this case:

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return TextScaler<TextScalingFactor>(
initialScaleFactor: TextScalingFactor(scaleFactor: 1.25),
child: MaterialApp(
title: 'Text Scaling Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Text Scaling Demo'),
),
);
}
}

Finally, we can use the scale factor in all the Text widgets throughout the app in this way:

Text(
'This is a sample heading',
textScaleFactor: TextScaler.of<TextScalingFactor>(context).scaleFactor,
)

And we can update the values in this way:

TextScaler.update(context, TextScalingFactor(scaleFactor: 1.5));

Kudos to Akshat Sharma for suggesting this amazing approach!😄

Thank you for reading this article. If you liked this article, then clap 👏 as much as you can and share it with your friends. You can find the complete source code here:

--

--