Flutter富文本编辑器插件html_editor_enhanced_android_fix的使用
Flutter富文本编辑器插件html_editor_enhanced_android_fix的使用
html_editor_enhanced_android_fix
是一个用于在 Flutter 应用中实现富文本编辑功能的插件。它支持 Android、iOS 和 Web 平台,并提供了丰富的自定义选项来满足不同需求。
安装插件
首先,在 pubspec.yaml
文件中添加 html_editor_enhanced_android_fix
插件依赖:
dependencies:
html_editor_enhanced_android_fix: ^2.5.0
然后运行 flutter pub get
来安装依赖。
Android 配置
确保在 AndroidManifest.xml
中声明互联网权限:
<uses-permission android:name="android.permission.INTERNET"/>
基本使用
以下是一个基本的使用示例:
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced_android_fix/html_editor.dart';
void main() => runApp(HtmlEditorExampleApp());
class HtmlEditorExampleApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
darkTheme: ThemeData.dark(),
home: HtmlEditorExample(title: 'Flutter HTML Editor Example'),
);
}
}
class HtmlEditorExample extends StatefulWidget {
HtmlEditorExample({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
_HtmlEditorExampleState createState() => _HtmlEditorExampleState();
}
class _HtmlEditorExampleState extends State<HtmlEditorExample> {
final HtmlEditorController controller = HtmlEditorController();
[@override](/user/override)
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (!kIsWeb) {
controller.clearFocus();
}
},
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
elevation: 0,
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
if (kIsWeb) {
controller.reloadWeb();
} else {
controller.editorController!.reload();
}
})
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
controller.toggleCodeView();
},
child: Text(r'<\>', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
HtmlEditor(
controller: controller,
htmlEditorOptions: HtmlEditorOptions(
hint: 'Your text here...',
shouldEnsureVisible: true,
),
htmlToolbarOptions: HtmlToolbarOptions(
toolbarPosition: ToolbarPosition.aboveEditor,
toolbarType: ToolbarType.nativeScrollable,
onButtonPressed: (ButtonType type, bool? status, Function? updateStatus) {
print("button '${describeEnum(type)}' pressed, the current selected status is $status");
return true;
},
onDropdownChanged: (DropdownType type, dynamic changed, Function(dynamic)? updateSelectedItem) {
print("dropdown '${describeEnum(type)}' changed to $changed");
return true;
},
mediaLinkInsertInterceptor: (String url, InsertFileType type) {
print(url);
return true;
},
mediaUploadInterceptor: (PlatformFile file, InsertFileType type) async {
print(file.name); //filename
print(file.size); //size in bytes
print(file.extension); //file extension (eg jpeg or mp4)
return true;
},
),
otherOptions: OtherOptions(height: 550),
callbacks: Callbacks(
onBeforeCommand: (String? currentHtml) {
print('html before change is $currentHtml');
},
onChangeContent: (String? changed) {
print('content changed to $changed');
},
onChangeCodeview: (String? changed) {
print('code changed to $changed');
},
onChangeSelection: (EditorSettings settings) {
print('parent element is ${settings.parentElement}');
print('font name is ${settings.fontName}');
},
onDialogShown: () {
print('dialog shown');
},
onEnter: () {
print('enter/return pressed');
},
onFocus: () {
print('editor focused');
},
onBlur: () {
print('editor unfocused');
},
onBlurCodeview: () {
print('codeview either focused or unfocused');
},
onInit: () {
print('init');
},
onImageUploadError: (FileUpload? file, String? base64Str, UploadError error) {
print(describeEnum(error));
print(base64Str ?? '');
if (file != null) {
print(file.name);
print(file.size);
print(file.type);
}
},
onKeyDown: (int? keyCode) {
print('$keyCode key downed');
print('current character count: ${controller.characterCount}');
},
onKeyUp: (int? keyCode) {
print('$keyCode key released');
},
onMouseDown: () {
print('mouse downed');
},
onMouseUp: () {
print('mouse released');
},
onNavigationRequestMobile: (String url) {
print(url);
return NavigationActionPolicy.ALLOW;
},
onPaste: () {
print('pasted into editor');
},
onScroll: () {
print('editor scrolled');
},
),
plugins: [
SummernoteAtMention(
getSuggestionsMobile: (String value) {
var mentions = ['test1', 'test2', 'test3'];
return mentions
.where((element) => element.contains(value))
.toList();
},
mentionsWeb: ['test1', 'test2', 'test3'],
onSelect: (String value) {
print(value);
},
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.undo();
},
child: Text('Undo', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.clear();
},
child: Text('Reset', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
var txt = await controller.getText();
if (txt.contains('src=\"data:')) {
txt = '<text removed due to base-64 data, displaying the text could cause the app to crash>';
}
setState(() {
result = txt;
});
},
child: Text(
'Submit',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.redo();
},
child: Text(
'Redo',
style: TextStyle(color: Colors.white),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(result),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.disable();
},
child: Text('Disable', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.enable();
},
child: Text(
'Enable',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.insertText('Google');
},
child: Text('Insert Text', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller
.insertHtml('<p style="color: blue">Google in blue</p>');
},
child: Text('Insert HTML', style: TextStyle(color: Colors.white)),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.insertLink(
'Google linked', 'https://google.com', true);
},
child: Text(
'Insert Link',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.insertNetworkImage(
'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png',
filename: 'Google network image');
},
child: Text(
'Insert network image',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Info notification', NotificationType.info);
},
child: Text('Info', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Warning notification', NotificationType.warning);
},
child: Text('Warning', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.addNotification(
'Success notification', NotificationType.success);
},
child: Text(
'Success',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.addNotification(
'Danger notification', NotificationType.danger);
},
child: Text(
'Danger',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Plaintext notification', NotificationType.plaintext);
},
child: Text('Plaintext', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.removeNotification();
},
child: Text(
'Remove',
style: TextStyle(color: Colors.white),
),
),
],
),
),
],
),
),
),
);
}
}
API 参考
参数 - HtmlEditor
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
controller | HtmlEditorController | 空 | 必需参数。创建一个控制器实例并传递给小部件。这确保任何方法仅在其HtmlEditor 实例上工作,允许在一个页面上使用多个HTML小部件。 |
callbacks | Callbacks | 空 | 自定义各种事件的回调。 |
options | HtmlEditorOptions | HtmlEditorOptions() | 设置各种选项的类。更多详情见下文。 |
plugins | List<Plugins> | 空 | 自定义激活哪些插件。更多详情见下文。 |
toolbar | List<Toolbar> | 见小部件的构造函数 | 自定义工具栏上显示的按钮及其顺序。更多详情见下文。 |
参数 - HtmlEditorController
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
processInputHtml | bool | true | 确定是否对任何输入HTML进行处理(例如转义引号、撇号并移除\n s)。 |
processNewLineAsBr | bool | false | 确定任何输入HTML中的新行(\n )是否变为<br/> 。 |
processOutputHtml | bool | true | 确定是否对任何输出HTML进行处理(例如<p><br/></p> 变为"" )。 |
参数 - HtmlEditorOptions
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
autoAdjustHeight | bool | true | 自动调整文本编辑器的高度。建议值为true 。 更多详情见下文。 |
adjustHeightForKeyboard | bool | true | 如果键盘处于活动状态且重叠了编辑器,则调整编辑器高度以防止重叠。建议值为true ,仅在移动设备上有效。 更多详情见下文。 |
filePath | String | 空 | 允许指定要加载到webview中的自定义HTML。您可以创建一个带有Summernote的自定义页面,或理论上加载任何其他编辑器/HTML。 |
shouldEnsureVisible | bool | false | 当webview聚焦时,将父Scrollable滚动到编辑器小部件的顶部。 不要在HtmlEditor 不在Scrollable 内时使用此参数。 更多详情见下文。 |
webInitialScripts | UnmodifiableListView<WebScript> | 空 | 轻松注入脚本来执行操作,如更改编辑器的背景颜色。 更多详情见下文。 |
参数 - HtmlToolbarOptions
参数 | 类型 | 默认值 | 描述 |
---|---|---|---|
customToolbarButtons | List<Widget> | 空 | 向工具栏添加自定义按钮。 |
customToolbarInsertionIndices | List<int> | 空 | 允许设置每个自定义工具栏按钮应插入到工具栏小部件列表的位置。 |
onButtonPressed | FutureOr<bool> Function(ButtonType, bool?, void Function()?) | 空 | 截获任何按钮按下事件。该函数传递按下的按钮枚举、当前选择状态(如果适用)以及更新状态的函数(如果适用)。 |
onDropdownChanged | FutureOr<bool> Function(DropdownType, dynamic, void Function(dynamic)?) | 空 | 截获任何下拉框更改事件。该函数传递更改的下拉框枚举、更改的值以及更新更改值的函数(如果适用)。 |
示例
示例代码
以下是一个完整的示例代码,展示了如何使用 html_editor_enhanced_android_fix
插件创建一个富文本编辑器:
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced_android_fix/html_editor.dart';
void main() => runApp(HtmlEditorExampleApp());
class HtmlEditorExampleApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
darkTheme: ThemeData.dark(),
home: HtmlEditorExample(title: 'Flutter HTML Editor Example'),
);
}
}
class HtmlEditorExample extends StatefulWidget {
HtmlEditorExample({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
_HtmlEditorExampleState createState() => _HtmlEditorExampleState();
}
class _HtmlEditorExampleState extends State<HtmlEditorExample> {
final HtmlEditorController controller = HtmlEditorController();
[@override](/user/override)
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
if (!kIsWeb) {
controller.clearFocus();
}
},
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
elevation: 0,
actions: [
IconButton(
icon: Icon(Icons.refresh),
onPressed: () {
if (kIsWeb) {
controller.reloadWeb();
} else {
controller.editorController!.reload();
}
})
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
controller.toggleCodeView();
},
child: Text(r'<\>', style: TextStyle(fontWeight: FontWeight.bold, fontSize: 18)),
),
body: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
HtmlEditor(
controller: controller,
htmlEditorOptions: HtmlEditorOptions(
hint: 'Your text here...',
shouldEnsureVisible: true,
),
htmlToolbarOptions: HtmlToolbarOptions(
toolbarPosition: ToolbarPosition.aboveEditor,
toolbarType: ToolbarType.nativeScrollable,
onButtonPressed: (ButtonType type, bool? status, Function? updateStatus) {
print("button '${describeEnum(type)}' pressed, the current selected status is $status");
return true;
},
onDropdownChanged: (DropdownType type, dynamic changed, Function(dynamic)? updateSelectedItem) {
print("dropdown '${describeEnum(type)}' changed to $changed");
return true;
},
mediaLinkInsertInterceptor: (String url, InsertFileType type) {
print(url);
return true;
},
mediaUploadInterceptor: (PlatformFile file, InsertFileType type) async {
print(file.name); //filename
print(file.size); //size in bytes
print(file.extension); //file extension (eg jpeg or mp4)
return true;
},
),
otherOptions: OtherOptions(height: 550),
callbacks: Callbacks(
onBeforeCommand: (String? currentHtml) {
print('html before change is $currentHtml');
},
onChangeContent: (String? changed) {
print('content changed to $changed');
},
onChangeCodeview: (String? changed) {
print('code changed to $changed');
},
onChangeSelection: (EditorSettings settings) {
print('parent element is ${settings.parentElement}');
print('font name is ${settings.fontName}');
},
onDialogShown: () {
print('dialog shown');
},
onEnter: () {
print('enter/return pressed');
},
onFocus: () {
print('editor focused');
},
onBlur: () {
print('editor unfocused');
},
onBlurCodeview: () {
print('codeview either focused or unfocused');
},
onInit: () {
print('init');
},
onImageUploadError: (FileUpload? file, String? base64Str, UploadError error) {
print(describeEnum(error));
print(base64Str ?? '');
if (file != null) {
print(file.name);
print(file.size);
print(file.type);
}
},
onKeyDown: (int? keyCode) {
print('$keyCode key downed');
print('current character count: ${controller.characterCount}');
},
onKeyUp: (int? keyCode) {
print('$keyCode key released');
},
onMouseDown: () {
print('mouse downed');
},
onMouseUp: () {
print('mouse released');
},
onNavigationRequestMobile: (String url) {
print(url);
return NavigationActionPolicy.ALLOW;
},
onPaste: () {
print('pasted into editor');
},
onScroll: () {
print('editor scrolled');
},
),
plugins: [
SummernoteAtMention(
getSuggestionsMobile: (String value) {
var mentions = ['test1', 'test2', 'test3'];
return mentions
.where((element) => element.contains(value))
.toList();
},
mentionsWeb: ['test1', 'test2', 'test3'],
onSelect: (String value) {
print(value);
},
),
],
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.undo();
},
child: Text('Undo', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.clear();
},
child: Text('Reset', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
var txt = await controller.getText();
if (txt.contains('src=\"data:')) {
txt = '<text removed due to base-64 data, displaying the text could cause the app to crash>';
}
setState(() {
result = txt;
});
},
child: Text(
'Submit',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.redo();
},
child: Text(
'Redo',
style: TextStyle(color: Colors.white),
),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(result),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.disable();
},
child: Text('Disable', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.enable();
},
child: Text(
'Enable',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.insertText('Google');
},
child: Text('Insert Text', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller
.insertHtml('<p style="color: blue">Google in blue</p>');
},
child: Text('Insert HTML', style: TextStyle(color: Colors.white)),
),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.insertLink(
'Google linked', 'https://google.com', true);
},
child: Text(
'Insert Link',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.insertNetworkImage(
'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_92x30dp.png',
filename: 'Google network image');
},
child: Text(
'Insert network image',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Info notification', NotificationType.info);
},
child: Text('Info', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Warning notification', NotificationType.warning);
},
child: Text('Warning', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.addNotification(
'Success notification', NotificationType.success);
},
child: Text(
'Success',
style: TextStyle(color: Colors.white),
),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () {
controller.addNotification(
'Danger notification', NotificationType.danger);
},
child: Text(
'Danger',
style: TextStyle(color: Colors.white),
),
),
],
),
),
SizedBox(height: 16),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
style: TextButton.styleFrom(backgroundColor: Colors.blueGrey),
onPressed: () {
controller.addNotification(
'Plaintext notification', NotificationType.plaintext);
},
child: Text('Plaintext', style: TextStyle(color: Colors.white)),
),
SizedBox(width: 16),
TextButton(
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.secondary),
onPressed: () async {
controller.removeNotification();
},
child: Text(
'Remove',
style: TextStyle(color: Colors.white),
),
),
],
),
),
],
),
),
),
);
}
}
更多关于Flutter富文本编辑器插件html_editor_enhanced_android_fix的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter富文本编辑器插件html_editor_enhanced_android_fix的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
html_editor_enhanced_android_fix
是一个用于 Flutter 的富文本编辑器插件,它基于 html_editor_enhanced
,并修复了一些在 Android 平台上的问题。这个插件允许你在 Flutter 应用中嵌入一个功能丰富的 HTML 编辑器,支持文本格式化、插入图片、链接等功能。
安装
首先,你需要在 pubspec.yaml
文件中添加 html_editor_enhanced_android_fix
插件的依赖:
dependencies:
flutter:
sdk: flutter
html_editor_enhanced_android_fix: ^1.0.0
然后运行 flutter pub get
来安装依赖。
基本用法
以下是一个简单的示例,展示了如何在 Flutter 应用中使用 html_editor_enhanced_android_fix
插件:
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced_android_fix/html_editor.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter HTML Editor',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HtmlEditorExample(),
);
}
}
class HtmlEditorExample extends StatefulWidget {
[@override](/user/override)
_HtmlEditorExampleState createState() => _HtmlEditorExampleState();
}
class _HtmlEditorExampleState extends State<HtmlEditorExample> {
final HtmlEditorController controller = HtmlEditorController();
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('HTML Editor Enhanced Android Fix'),
actions: [
IconButton(
icon: Icon(Icons.save),
onPressed: () async {
final String? html = await controller.getText();
print(html);
},
),
],
),
body: SingleChildScrollView(
child: Column(
children: [
HtmlEditor(
controller: controller,
htmlEditorOptions: HtmlEditorOptions(
hint: "Your text here...",
shouldEnsureVisible: true,
),
htmlToolbarOptions: HtmlToolbarOptions(
defaultToolbarButtons: [
StyleButtons(),
FontSettingButtons(),
ListButtons(),
ParagraphButtons(),
InsertButtons(),
],
),
otherOptions: OtherOptions(
height: 300,
),
),
],
),
),
);
}
}