Building a Custom Rich Text Editor in Flutter: Analysis, JSON Configuration, and Core Modules
This article analyzes the essential features of rich‑text editors, compares popular solutions, explains the choice of the Quill protocol, and provides a step‑by‑step guide with Flutter code to define JSON configurations, parse colors, create data models, and render rich text in a custom Flutter widget.
After introducing the importance of rich‑text editors in many apps, the article explains that Flutter’s basic TextField is insufficient for complex scenarios such as image insertion or ordered lists, prompting the need for a custom solution.
It compares several well‑known editors (Quill, wangEditor, ProseMirror) and selects the Quill open‑source license for the project.
FlutterQuill analysis covers the core components required to build a rich‑text editor, including:
Defining a JSON configuration file to store text and style information.
Parsing color strings (both rgba(...) and hex formats) into Color objects.
Creating a TextRichInfo data class with fields for message, style map, color, size, and insert marker.
Implementing a method that decodes the JSON, converts each entry into a TextSpan with the appropriate TextStyle , and adds line breaks when needed.
Using the generated list of TextSpan objects in a RichText widget via Text.rich .
Key code snippets:
[
{
"insert": "Flutter Quill",
"attributes": {"header": 1}
},
{"insert": "\n"}
] Color stringToColor(String s) {
if (s.startsWith('rgba')) {
s = s.substring(5);
s = s.substring(0, s.length - 1);
var arr = s.split(',').map((e) => e.trim()).toList();
return Color.fromRGBO(int.parse(arr[0]), int.parse(arr[1]), int.parse(arr[2]), double.parse(arr[3]));
} else if (s.startsWith('#')) {
s = s.toUpperCase().replaceAll('#', '');
if (s.length == 6) s = "FF$s";
return Color(int.parse(s, radix: 16));
}
return const Color.fromRGBO(0, 0, 0, 0);
} class TextRichInfo {
String? message;
Map
? richTexts;
String? color;
int? textSize;
String? insert;
TextRichInfo({this.message, this.richTexts, this.color, this.textSize, this.insert});
TextRichInfo.fromJson(Map
json) {
message = json["message"];
richTexts = json["richTexts"];
color = richTexts!["color"];
textSize = richTexts!["textSize"];
insert = json["insert"] ?? null;
}
} List
_textSpanList() {
List
spanList = [];
var textJsonMap = json.decode(widget.richTextJsonConfig);
for (var i in textJsonMap) {
var data = TextRichInfo.fromJson(i);
spanList.add(TextSpan(text: data.message, style: TextStyle(color: stringToColor(data.color!), fontSize: data.textSize!.toDouble())));
if (data.insert != null) spanList.add(const TextSpan(text: "\n"));
}
return spanList;
}Finally, the article shows how to use the widget:
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: RichTextEditor(
richTextJsonConfig: r'[{"message":"Flutter Editor Taxze","richTexts":{"color":"#e60000","textSize":32},"insert":"\n"},...]',
),
),
);
}The conclusion summarizes that the article has identified required features, examined FlutterQuill, and demonstrated a basic implementation of JSON‑driven rich‑text rendering, with a promise to explore deeper custom editor development in the next part.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.