-
Notifications
You must be signed in to change notification settings - Fork 249
RESEARCH: Can we use existing widgets?
We're building a rich text editor in Flutter. The most economical approach is to use existing widgets, wherever possible. However, we must take care when embracing existing widgets. A given widget might work for immediate needs, but be fundamentally unacceptable for known, future needs.
This document describes the analysis of various, existing Flutter widgets with regard to their suitability for use within this rich text editor implementation.
In theory, a TextField
widget could represent a single editable paragraph or list item within a rich text editor. Would that make sense?
https://api.flutter.dev/flutter/material/TextField-class.html
A TextField
is described as an implementation of a "Material text field". In other words, the appearance and interactions implemented within a TextField
adhere to the requirements of a standalone Material component for text entry. This use-case is so narrow that the documentation suggests a different widget should be used to achieve a "Cupertino" style. Given the specificity of the TextField
s visual design and user interactions, it does not make sense to utilize TextField
widgets within the rich text editor's implementation. Invariably, a lot of work would go into undoing behavior within TextField
. Furthermore, TextField
may implement undesired behaviors that can't be turned off or avoided.
TextField
does not appear to be a legitimate option for implementing a rich text editor.
In theory, a EditableText
widget could represent a single editable paragraph or list item within a rich text editor. Would that make sense?
https://api.flutter.dev/flutter/widgets/EditableText-class.html
The EditableText
widget is the workhorse for all text entry in Flutter, including the implementation of a TextField
. EditableText
is definitely a more appropriate alternative to TextField
because EditableText
avoids the opinionated Material component behaviors of TextField
.
The documentation for EditableText
references capabilities including: text selection, text entry, copy/paste popups, Android and iOS input actions, cursor appearance, and more. Are these behaviors helpful, harmful, or irrelevant for the rich text editor?
- Android and iOS input actions: irrelevant for the rich text editor. We'll want to disable these because a mobile input field action like "Done" or "Emergency Call" or "Search" would make no sense for a paragraph or a list item in a rich text editor.
- Cursor control:
EditableText
offers control over the cursor when it enters the widget. But this control is not specific enough. We need to control the cursor based on its position over actual text. This is a possible failure point. - Copy/Paste controls:
EditableText
includes the concept of a "toolbar", which can be configured to support a combination of cut, copy, and paste. The rich text editor needs to allow for a completely custom toolbar UI, and any given selection of actions. Those actions, including cut, copy, and paste must also defer to custom implementations. There is some level of control over the toolbar implementation. This is a possible failure point. - Text selection:
EditableText
supports text selection within itself. A quick experiment indicates that selection can't happen acrossEditableText
s using the standard implementation. I don't see any obvious place to override selection behavior to the degree that one could implement cross-widget selection. It might be possible to extend the underlyingRenderObject
and override the selection behavior from there. This is a likely failure point. - Scrolling:
EditableText
has scrolling built in. This will never be a desired capability for individual paragraphs or list items. It's a waste of widget tree build cycles, and layout cycles.
EditableText
, or its underlying RenderEditable
, might be appropriate for early development. It is probably not desirable for the final product because we don't need some of the internal widgets. For example: we never want scrolling on an individual paragraph basis, but every EditableText
includes a Scrollable
widget. We need to implement our own cursor control based on exact text boxes, which will override the MouseRegion
widget within every EditableText
. We may also want to avoid inheriting a bunch of unnecessary behaviors because if those behaviors change in the future, it might break the rich text editor.
A Text
widget is reasonable for text display, including rich text display. A rich text editor spike demonstrates that custom selection can be implemented with Text
widgets in a regular widget tree.
However, all text displayed in the rich text editor must editable. There are no read-only requirements at the time of writing this analysis.
Theoretically, a Text
widget could be used inside of a custom RichTextEditable
widget. The Text
widget would handle display responsibilities and the rest of the RichTextEditable
would handle all other responsibilities, e.g., selection, text input, commands, etc. This might be a legitimate approach to early parts of the project. The final implementation might be better served with a custom RenderObject
that extends or re-implements RenderParagraph
.