lightweight_rich_editor
A rich-text editor for Flutter that draws your note on ruled paper. It is
built on a single TextField, so scrolling, selection, IME input and accessibility are the ones Flutter already
gives you.
The API may still change before 1.0.
What it does
- Bold, italic, underline, strikethrough, inline code, text colour, highlight and font size.
- Headings, bullet, numbered and checklist items (up to six levels deep), horizontal rules.
- Fenced code blocks with a language label and syntax colouring.
- Pictures that sit in the text as blocks of rows. You choose where the bytes are stored.
- Links, with a small bar to open, copy, edit or remove the one you tapped.
- Find and replace.
- Paste of HTML and Markdown (including from a browser), and export to Markdown and HTML.
- Undo and redo.
- Ruled, dashed, dotted and grid paper, with an optional margin line. Lines follow the real height of each row, so wrapped lines and headings stay on the paper.
- Read-only mode, whole-document text alignment and direction (RTL works).
- Save and load a document as JSON.
Platforms: Android, iOS, macOS, Windows, Linux and web. Native code is only used for reading and writing rich text on the clipboard.
Install
dependencies:
lightweight_rich_editor: ^0.3.0
Use it
LightweightRichEditor is the toolbar, the editor and the find bar in one widget:
import 'package:flutter/material.dart';
import 'package:lightweight_rich_editor/lightweight_rich_editor.dart';
class NoteScreen extends StatelessWidget {
const NoteScreen({super.key});
@override
Widget build(BuildContext context) {
return const Scaffold(
body: LightweightRichEditor(initialText: 'Hello, world!'),
);
}
}
To get at the controller, pass your own, or use a key:
final key = GlobalKey<LightweightRichEditorState>();
LightweightRichEditor(
key: key,
onSave: () => save(key.currentState!.controller.document.toJson()),
);
Using the pieces separately
FormatToolbar, RichTextEditor and FindReplaceBar can be placed wherever you like:
class _NoteState extends State<Note> {
late final _controller = RichEditorController(text: 'Hello World!');
final _scroll = ScrollController();
@override
void dispose() {
_controller.dispose();
_scroll.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
FormatToolbar(controller: _controller),
Expanded(
child: RichTextEditor(
controller: _controller,
scrollController: _scroll,
),
),
],
);
}
}
Changing how it looks
Text styling is in RichTextRenderTheme, the page (padding, ruled lines, margin) is in RichEditorStyle:
final controller = RichEditorController(
text: 'Custom editor',
theme: const RichTextRenderTheme(baseFontSize: 18),
);
const style = RichEditorStyle(ruledLineColor: Color(0x33808080));
Themes can be swapped while the editor is open, for example for dark mode. The text, selection and undo history stay as they are:
controller.renderer.theme = isDark ? darkTheme : RichTextRenderTheme.standard;
The package has no fonts, icons or theme of its own. Everything is a value you pass in. CUSTOMIZATION_GUIDE.md lists them all and covers the awkward cases, such as changing the font without pushing text off the ruled lines.
More
example/has a small app with dark mode and save/load.- EXTENSION_POINTS.md lists what the editor does not do, and why.
- Bugs and pull requests are welcome on GitHub.
License
MIT, see LICENSE. Copyright Kenresoft Technologies Ltd.