I'm wrestling with how RichText
handles nested spans that contain other RichText
instances. It works fine as long as the user doesn't change the phone's default font size. But if they have changed the display font size, things start going awry.
Consider the case where I'm parsing some HTML that looks like:
<underline><italic><bold>xxxxx</bold></italic></underline>
Conceptually this can be modelled as a TextSpan
inside a TextSpan
inside a TextSpan
, so I might have some contrived code that looks like:
class MyHomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final inputText = 'The quick brown fox jumped over the lazy dog. The quick brown fox jumped over the lazy dog.';
final initialSpan = TextSpan(text: inputText, style: TextStyle(color: Colors.black));
final boldText = _buildStyledElement(context, initialSpan, Style.bold);
final boldItalised = _buildStyledElement(context, WidgetSpan(child: boldText), Style.italic);
final boldItalisedUnderlined = _buildStyledElement(context, WidgetSpan(child: boldItalised), Style.underline);
return new Scaffold(
appBar: AppBar(title: Text('')),
body: Column(
children: [
Text(inputText), // a simple baseline to compare
boldText,
boldItalised,
boldItalisedUnderlined,
],
),
);
}
RichText _buildStyledElement(BuildContext context, InlineSpan span, Style style) {
// note we're not applying the style because it isn't important... the style parameter
// is just a means of wrapping our heads around a real-world example of nesting
return RichText(text: span);
}
}
As you can see on the left, it looks great with normal font size but on the right, the three RichText
cases don't scale when you adjust the phone's fonts size.
That's easy to explain though... because the default scaling factor for a RichText
is 1.0
so there's no scaling. Let's fix that by changing the creation code to look like:
return RichText(text: span, textScaleFactor: MediaQuery.of(context).textScaleFactor);
As you can see below, the normal font still looks good, but woah... things scale up real quickly due to the RichText
nesting (I'm assuming it is applying the scale factor onto already scaled children).
Now, one thing I've found is that if I allow all the RichText
widgets to be created using a scale factor of 1.0
, and then wrap the outermost in a RichText
that is using the device's scale factor, it /almost/ works. For example, remove the scaling in _buildStyledElement
and add this row into the main Column
widget:
RichText(text: WidgetSpan(child: boldItalisedUnderlined), textScaleFactor: MediaQuery.of(context).textScaleFactor),
As you can see, things look good at the normal font size and actually scale to the correct size for large fonts. However, the wrapping is now broken.
I'm assuming that this is because the size that is calculated by the child RichText
widgets (because they are using a scale factor of 1.0
) doesn't marry up with the total calculated space when using the media query's scale factor.
Sooo... I guess my question is whether there is a way to actually get this to work properly with nested RichText
instances. I know that for this specific example there may be some other options... but I'm talking about the general case where RichText
widgets embed other RichText
widgets.
Any thoughts would be much appreciated. Sorry for the long post.
Regardless of not having a definite solution there's a workaround that I found particularly useful for my purpose:
You need to set the text scale factor for the Html Widget fixed to 1, and choose a default font size for your average text on the HTML the multiply it to the current scale factor of the screen (not the fixed manually).
class ExampleWidget extends StatelessWidget {
final String data;
ExampleWidget({this.data});
@override
Widget build(BuildContext context) {
double scaleFactor = MediaQuery.of(context).textScaleFactor;
int standardFontSize = 14;
int h3FontSize = 18;
return MediaQuery(
data: MediaQueryData(textScaleFactor: 1),
child: Html(
data: data,
style: {
'body': Style(fontSize: FontSize(standardFontSize * scaleFactor)),
'h3': Style(fontSize: FontSize(h3FontSize * scaleFactor))
// other header fonts...
},
),
);
}
}
The downside is needing to manually implement every time you need a new font size but it might solve an urgent problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With