Last updated:
0 purchases
flutter rte
Flutter Rich Text Editor #
Easy to use WYSIWYG HTML editor for Flutter with built-in voice-to-text.
Try it here #
Under the Hood #
This plugin is a reworked html_editor_enhanced with a few differences:
Improved widget height constraints:
wrap content,
expand full height, or
explicit.
Summernote and jQuery replaced with Squire - very popular and well-maintained HTML5 rich text editor library, which provides great flexibility over generated HTML.
XSS protection enforced by DOMPurify - super-fast, uber-tolerant XSS sanitizer for HTML, MathML and SVG.
in_app_webview replaced with Flutter's own webview_flutter.
Built-in dictation feature powered by speech_to_text package (primarily for the web platform)
Basic Implementation #
Basic implementation of this editor doesn't require a controller. For simplicity and ease of use, [HtmlEditor] gives you access to the following top-level attributes:
Field
Type
Description
height
double
sets explicit height of the widget
minHeight
double
sets minimum height of the widget
expandFullHeight
bool
sizes widget to take all available height
hint
String
Displays hint text when the editor is empty
initialValue
String
initial HTML or text
onChanged
String
top-level shortcut to onChanged callback of the controller
isReadOnly
bool
locks the editor and removes the toolbar
enableDictation
bool
yay or nay to voice-to-text feature
import 'package:flutter_rte/flutter_rte.dart';
// ...
// 1. Define a var to store changes within parent class or a provider etc...
String result = 'Hello world!';
// ...
// 2. Add HtmlEditor to your build method
@override
Widget build(BuildContext context) =>
HtmlEditor(initalValue: result, onChanged:(s)=> result = s ?? '');
copied to clipboard
Advanced Implementation #
To take advantage of the entire API you'll need to create and configure an instance of [HtmlEditorController]. That instance provides access to the following groups of options:
Styling options group (all things CSS, HTML and sanitizing)
Toolbar options group (all things toolbar)
Editor options group (all things editor)
When using the controller, the text of HtmlEditor could be set via controller.setText() method. This could be done before or after the controller is attached to the HtmlEditor in the UI. This is useful for MVVM/MVC situations, where the logic is initialized before the UI is built.
Contents of the editor could be tried and accessed syncronously via a getter:
if(controller.contentIsNotEmpty){
Navigator.of(context).pop(controller.content);
}
copied to clipboard
HTML Styling Options #
The stylingOptions parameter of [HtmlEditorController] class defines the look of generated HTML. Here you can select which tag to use for paragraphs and how your tags are styled.
var stylingOptions = HtmlStylingOptions(
// Adding global style is optional, but could be set in two ways:
// 1. by providing a CSS string to the parameter `globalStyleSheet`:
globalStyleSheet: '/* Your CSS string contents of style.css file */',
// This defines which tag to use for paragraphs.
// The default value is `p`, however the `div` is also acceptable.
blockTag: 'p',
// defines `style` and `class` attributes of a block tag
blockTagAttributes: HtmlTagAttributes(
// this is added as inline CSS for every tag
inlineStyle: 'text-indent:3.5em; text-align:justify;',
// defines `class` attribute value of every tag
cssClass: 'my-custom-pgf'),
// next we can define attributes for other tags (li, ul, ol, a etc):
li: HtmlTagAttributes(
inlineStyle: 'margin: .5em 1em .5em .5em',
cssClass: 'my-custom-li-class'),
// ... other HTML tag definitions ... //
code: HtmlTagAttributes(
inlineStyle: 'padding: .5em 1em;', cssClass: 'my-custom-li-class'),
// when sanitizeOnPaste is `true` - editor will sanitize all incoming HTML.
// !!! DANGER !!! Setting this flag to `false` makes your app
// vulnerable to XSS attacks.
sanitizeOnPaste: true,
);
// 2. another way to add global CSS is to call this async method:
await stylingOptions.importCssFromFile('path/to/style.css');
// ...
// Now create the editor passing the styling options
return HtmlEditor(
controller: HtmlEditorController(stylingOptions: stylingOptions),
onChanged: (p0) => (p0) {/* TODO */},
initialValue: '' /* TODO */,
);
copied to clipboard
The code above should result in the following HTML being generated for each paragraph:
<p style="text-indent:3.5em; text-align:justify;" class="my-custom-pgf"></p>
copied to clipboard
Sizing and Constraints #
By default, the widget occupies all available width and sizes its height based on the height of its content, but not less than the value of minHeight attribute of [HtmlEditor] widget.
// since explicit height is not provided - the editor will size itself
// based on content, but will be not less than 250px
return HtmlEditor(
controller: controller,
// ...
minHeight: 250, // should be not less than 64px
// ...
);
// and here you can listen to changes in height of the editor
ValueListenableBuilder<double>(
valueListenable: controller.totalHeight,
builder: (BuildContext context, double value, Widget? child) {
return Text('Height changed to $value\n'
'Toolbar height is ${controller.toolbarHeight}\n'
'Content height is ${controller.contentHeight}\n' );
});
copied to clipboard
If explicit `height` is provided - the widget will size it's height precisely to the value of `height` attribute. In this case, if content height is greater than the widget height - the content becomes scrollable.
// here we've provided the height value, so the editor will always be
// that height and the content will scroll if overflows the height.
return HtmlEditor(
height: 250,
);
copied to clipboard
If `expandFullHeight` is set to `true` - the widget will take up all available height.
return HtmlEditor(
expandFullHeight: true,
);
copied to clipboard
Toolbar Position #
All toolbar-related options are contained within [ToolbarOptions] of [HtmlEditorController] class. Toolbar could be positionned:
above or below the editor container, by setting the toolbarPosition attribute;
Above editor:
Below editor:
detached from the editor and located anywhere outside the [HtmlEditor]widget. This allows [ToolbarWidget] to be attached to several HtmlEditors. For this type of implementation please refer to the example within the package.
scrollable, grid or expandable by setting the toolbarType attribute
Toolbar Contents and Custom Button Groups #
Toolbar button groups could be enabled/disabled via defaultToolbarButtons attribute of [HtmlToolbarOptions] class within the controller. You can customize the toolbar by overriding the default value of this attribute.
To add your own button group to the toolbar, you need to provide a list of [CustomButtonGroup] objects to the customButtonGroups attribute. Each button group will consist of a list of [CustomToolbarButton] objects, each with its own icon, tap callback and an isSelected flag to let the toolbar know if the icon button should be highlighted.
HtmlEditor(
controller: HtmlEditorController()
..toolbarOptions.customButtonGroups = [
CustomButtonGroup(
index: 0, // place first
buttons: [
CustomToolbarButton(
icon: Icons.save_outlined,
action: () => /* TODO: implement your save method */,
isSelected: false)
])
],
),
copied to clipboard
=
Voice to Text (Dictation) #
Voice-to-text feature is powered by speech_to_text package and comes enabled by default with this package.
To disable voice-to-text feature - set the corresponding top-level enableDictation attribute within [HtmlEditor] constructor to false.
Overriding controller.toolbarOptions.defaultToolbarButtons value also overrides enableDictation flag (obviously), so you need to add const VoiceToTextButtons() in order to keep seeing the voice-to-text button.
Special Considerations and Gotchas #
Due to some framework issues on Web, this plugin is only compatible with Flutter 3.3 and up. If you want to use this plugin with earlier versions of Flutter - make sure to downgrade pointer_interceptor dependency in your project to 0.9.0+1.
Following needs to be done to make things work on each platform:
Android #
For speech recognition to work - place this to android > app > src > main > AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.example">
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<application
...
copied to clipboard
iOS #
For speech recognition to work - add following permission to your Info.plist file:
<key>NSSpeechRecognitionUsageDescription</key>
<string>recognize speech</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for uploading videos</string>
copied to clipboard
Web Platform #
To get the toolbar to scroll horizontally on Web, you will need to make sure you override the default scroll behavior:
Add the following class override to your app:
class MyCustomScrollBehavior extends MaterialScrollBehavior {
@override
Set<PointerDeviceKind> get dragDevices => {
PointerDeviceKind.touch,
PointerDeviceKind.mouse,
};
}
copied to clipboard
Add the following attribute to the [MaterialApp] widget:
return MaterialApp(
// ...
scrollBehavior: MyCustomScrollBehavior(),
// ...
);
copied to clipboard
Done. Now you should be able to drag the toolbar left and right on web.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.