Mobile Development 13 min read

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.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Building a Custom Rich Text Editor in Flutter: Analysis, JSON Configuration, and Core Modules

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.

DartFluttermobile developmentuiJSONRich Text Editor
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.