Get Flutter text layout super powers with Super Text Layout

Matt Carroll
Super Declarative!
4 min readMay 18, 2022

--

Flutter makes it easy to paint some plain text, and also makes it easy to add a pre-built, Material Design compliant text field into your app. Flutter makes it very difficult to do anything in-between. The Flutter Bounty Hunters and Superlist are here to make all of it easy! We’ve released super_text_layout to help you decorate your text however you’d like.

A different color for every character’s bounding box

Quickstart

For those looking for the fastest way to get started with super_text_layout, the package includes a widget called SuperTextWithSelection, which provides typical caret and selection painting with more customization control than a standard Flutter SelectableText widget, but with less generality than the SuperText widget.

// Text that paints a single user's caret + selection highlight.
SuperTextWithSelection.single(
richText: _text,
userSelection: const UserSelection(
highlightStyle: _primaryHighlightStyle,
caretStyle: _primaryCaretStyle,
selection: TextSelection(baseOffset: 11, extentOffset: 21),
),
);
A SuperTextWithSelection widget

How text layout works

Every blob of text that Flutter paints is backed by a Text widget, which internally relies upon a RenderParagraph. The RenderParagraph is the object that constrains the text box, lays out the text, and paints the characters. After the layout pass, the RenderParagraph exposes information about the bounding boxes for lines of text, bounding boxes for individual characters, and offsets for specific text positions. This information makes it possible to add widgets and paint pixels around lines and characters.

RenderParagraph reports a rectangle for every character

The “next frame” problem

Flutter developers want to work with Widgets, rather than RenderObjects, because Widgets are much faster and easier to compose. They’re also far simpler than RenderObjects. However, if we try to access a RenderParagraph from our Widget tree, we’re always one frame behind the text layout. This is because we can’t query the text layout until after the RenderParagraph runs layout. Thus, the Text widget runs layout on Frame 1, and then our custom text layout code runs on Frame 2.

Flutter’s “next frame” problem

Running your custom layout one frame behind isn’t a big deal from a UX standpoint. You probably won’t even notice it. But the extra frame introduces code complexity because your code has to handle the possibility that the RenderParagraph isn’t laid out yet. This is doubly annoying because RenderParagraph doesn’t tell you whether or not it’s laid out. You have to wrap your calls with try/catch blocks, just in case the RenderParagraph blows up when you try to access a bounding box, or a text offset.

I’m happy to report that, working with Flutter Bounty Hunter Specialist, Simon Lightfoot, we’ve implemented our SuperText widget in a way that solves this “next frame” problem. With SuperText you can use Widgets to decorate your text, and your decoration Widgets will be laid out and painted within the exact same frame as the text that you’re decorating. This is a big win for super_text_layout, and I’m not aware of any other Flutter text tool that currently provides this super power.

super_text_layout test that verifies decorations are built in the same frame as the text layout

Super Text Layout is already used in production

For those who have paid attention to what we’ve been working on at the Flutter Bounty Hunters, you know that Super Editor has been our primary focus for quite a while. Super Text Layout is a convenient repackaging of text decoration tools that we’ve built into Super Editor over time. As a custom document editor toolkit, Super Editor has always required custom selection painting. Eventually, we decided that all Flutter developers could benefit from the ability to quickly and easily decorate text layout. We cleaned up the code, solved the “next frame” problem, added some tests, and published super_text_layout. Now you can easily implement your own text highlights, carets, handles, or 90s style sparkle effects!

If your team would like to see additional features in super_text_layout, or if your team would like for the Flutter Bounty Hunters to build open source tools to support your product, please reach out to us!

--

--