Inline widgets in Flutter #392
Replies: 2 comments 6 replies
-
@matthew-carroll, using the demo from #393 and resizing the window it seems that flutter handles the multi-line scenario: Or did I understood wrongly what is the limitation? |
Beta Was this translation helpful? Give feedback.
-
How about something like a table? I guess a table usually wouldn't be inline, but that would reasonably need to support rich text formatting within the table widget. I think it would be worthwhile for Flutter to invest in supporting multiline inline widgets. People probably already expect that to work in RichText. Any idea if there is an issue for that or should I create one? I wonder if @chunhtai has any opinion on attributing rich text having worked on Flutter's AttributedString. |
Beta Was this translation helpful? Give feedback.
-
Super Editor needs to support various inline non-text visuals. Generically speaking, this means small widgets that sit within a block of text.
Three major questions that we need to answer include:
Rendering inline content with Flutter
Flutter's rich text layout is based on a tree of InlineSpans. The root span for a block of text is a TextSpan. A
TextSpan
can display genericWidget
s inline by configuring one or more WidgetSpans as the children for theTextSpan
.Example:
Based on a coding spike, it looks like Flutter is capable of rendering the nominal case for the most common use-cases:
Possible problems
Structuring non-text content
Super Editor's representation of text with styles and metadata is called
AttributedText
.AttributedText
allows for any number of overlapping attributions that span any number of characters of text.Currently,
AttributedText
has no concept of non-text content.It's possible that inline widgets could be supported without changing
AttributedText
. The following is a proposal that I received:In practice, splitting a single text block into multiple
AttributedText
segments is probably impractical. User selections and attributions might cross the inline widget and impact multipleAttributedText
instances. This proposal would likely require individual app developers to coordinate content and attribution changes across multipleAttributedText
instances. That would be very cumbersome and developers might avoid Super Editor due to that difficulty.A more useful solution would find a way to utilize
AttributedText
to reference non-text content such that the non-text content can be rendered and selected without makingAttributedText
aware of non-text content.To get a feel for what this might look like, consider the following use-cases. Keep in mind that this is just a proposal for what the content structure might look like; this structure doesn't solve rendering or user interaction.
Inline Icon
One might display an inline icon in the following ways.
Replace an arbitrary character with an icon bitmap:
Replace a substring with an icon bitmap:
Inline avatar
An inline avatar could be attributed in a similar fashion to an inline icon:
Inline code
Inline code could be attributed in a similar fashion to an inline icon:
A downside to this approach is that the app developer needs to keep the code in
InlineCodeAttribution
in sync with the content ofAttributedText
. For example, consider what happens when the user deletes a character within the inline code attribution.An adjustment to this approach might be to give the attribution renderer more insight into the content that it's rendering so that the renderer can inspect the
AttributedText
, find the inline code text, and then pass that to the inline widget.Rendering
AttributedText
with non-text contentRendering is where things start to get tricky.
As a reminder, the process for rendering
AttributedText
involves chopping up theAttributedText
at every attribution marker, passing a set of attributions into a function, and then that function returns aTextSpan
. TheTextSpan
s are accumulated into a list and then passed to aRichText
widget. Obviously, we'll need to generalize the return type of the render function toInlineSpan
, but that's a minor change.The simplest case
Looking at displaying inline widgets, the simplest case is one in which the inline content has no other overlapping attributions:
"I am |@SuprDeclarative|"
In this case, the render function would return an appropriate
WidgetSpan
for theInlineAvatarAttribution
that surrounds "@SuprDeclarative". That should solve the simplest case for a non-selectable text replacement. This same approach would work the same way for an icon replacement.Overlapping attributions
In the case of something like inline code, we have the possibility that an attribution, like bold, partially overlaps the inline widget attribution:
In this scenario, the render function is going to receive text that is chopped up into the following groups:
Notice that the above segmentation prevents the render function from combining "This is" and " some code" into a single widget. For this reason, the render function might need some new look-ahead capabilities so that it can collect additional groups of text.
Another option is to prohibit any attributions from overlapping an inline widget attribution. I'm hesitant to go down that route because we have no idea what kind of metadata developers might want to inject into their text, including inline widget content.
Inline widget interaction
The most complicated part of inline widget content is working that content into existing editor interactions.
Consider the following:
Super Editor currently has two levels of user interaction. At the higher level, the user can interact with the document layout and document selection. At the lower level, the user can interact with a text layout and text selection.
The introduction of selectable, editable inline arbitrary content introduces a 3rd level of layout and selection that sits beneath that of the text layout. Super Editor now needs to support:
The total impact on the existing Super Editor implementation is unclear, however a couple details seem likely.
First, Super Editor will need to replace its use of
TextSelection
with a broader concept that represents a mixture of selected text and selections of arbitrary inline content. This change is kind of like taking the complexity ofDocumentSelection
and applying it to everyTextNode
.Second, Super Editor will need to introduce a layout interface for every inline widget so that whenever the user taps or drags over the inline widget, Super Editor can query for the meaning of that position within the inline widget. For something like an icon, those answers are simple - any area over the icon indicates an icon selection. However, for something like inline code, the inline code needs to translate the given offset to the corresponding character of text within the inline code widget.
Conclusion
At this moment, I think we can say:
AttributedText
can already be used to structure inline content.AttributedText
rendering system should allow for inline widget rendering.Beta Was this translation helpful? Give feedback.
All reactions