Get Flutter text layout super powers with Super Text Layout
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.
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),
),
);
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.
The “next frame” problem
Flutter developers want to work with Widget
s, rather than RenderObject
s, because Widget
s are much faster and easier to compose. They’re also far simpler than RenderObject
s. 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.
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 Widget
s to decorate your text, and your decoration Widget
s 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 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!