Flutter富文本编辑器插件flutter_rte的使用

发布于 1周前 作者 yuanlaile 来自 Flutter

Flutter富文本编辑器插件flutter_rte的使用

简介

flutter_rte 是一个易于使用的所见即所得(WYSIWYG)HTML编辑器,适用于Flutter,并内置了语音转文字功能。该插件基于 html_editor_enhanced 进行改进,提供了更好的高度约束、更灵活的HTML生成以及XSS防护等功能。

尝试在线演示

你可以在这里尝试在线演示:Flutter Rich Text Editor Web

核心特性

  • 改进的高度约束:
    • 自适应内容高度
    • 扩展至全高
    • 显式设置高度
  • 使用 Squire 替代 Summernote 和 jQuery,提供更灵活的HTML5富文本编辑。
  • 使用 DOMPurify 提供超快的XSS防护。
  • 使用Flutter官方的 webview_flutter 替代 in_app_webview
  • 内置语音转文字功能(主要适用于Web平台),由 speech_to_text 包提供支持。

基本实现

基本实现不需要控制器,只需在 HtmlEditor 中设置一些简单的属性即可。

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String result = 'Hello world!';

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: HtmlEditor(
          initialValue: result,
          onChanged: (s) => setState(() => result = s ?? ''),
          hint: 'Enter your text here...',
        ),
      ),
    );
  }
}

高级实现

高级实现需要创建并配置 HtmlEditorController 实例,以访问更多的API选项,如样式选项、工具栏选项和编辑器选项等。

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final HtmlEditorController controller = HtmlEditorController();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            HtmlEditor(
              controller: controller,
              minHeight: 250,
              onChanged: (s) => print(s),
              initialValue: '<p>Hello, World!</p>',
            ),
            ElevatedButton(
              onPressed: () async {
                await controller.setText('<p>New content</p>');
              },
              child: Text('Set Content'),
            ),
            ElevatedButton(
              onPressed: () async {
                final content = await controller.getText();
                print(content);
              },
              child: Text('Get Content'),
            ),
          ],
        ),
      ),
    );
  }
}

HTML样式选项

通过 HtmlStylingOptions 参数可以定义生成HTML的样式。你可以选择段落标签和其他HTML标签的样式。

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final HtmlEditorController controller = HtmlEditorController();

  [@override](/user/override)
  void initState() {
    super.initState();
    var stylingOptions = HtmlStylingOptions(
      globalStyleSheet: '/* Your CSS string contents of style.css file */',
      blockTag: 'p',
      blockTagAttributes: HtmlTagAttributes(
        inlineStyle: 'text-indent:3.5em; text-align:justify;',
        cssClass: 'my-custom-pgf',
      ),
      li: HtmlTagAttributes(
        inlineStyle: 'margin: .5em 1em  .5em .5em',
        cssClass: 'my-custom-li-class',
      ),
      sanitizeOnPaste: true,
    );

    controller.setStylingOptions(stylingOptions);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: HtmlEditor(
          controller: controller,
          minHeight: 250,
          onChanged: (s) => print(s),
          initialValue: '<p>Hello, World!</p>',
        ),
      ),
    );
  }
}

工具栏位置与内容

你可以自定义工具栏的位置和内容,包括将工具栏放置在编辑器上方或下方,甚至将其分离出来放在其他地方。

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final HtmlEditorController controller = HtmlEditorController();

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: HtmlEditor(
          controller: controller,
          toolbarPosition: ToolbarPosition.aboveEditor,
          toolbarType: ToolbarType.scrollable,
          minHeight: 250,
          onChanged: (s) => print(s),
          initialValue: '<p>Hello, World!</p>',
        ),
      ),
    );
  }
}

语音转文字功能

默认情况下,语音转文字功能是启用的。如果你想禁用它,可以将 enableDictation 属性设置为 false

示例代码

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: HtmlEditor(
          enableDictation: false,
          minHeight: 250,
          onChanged: (s) => print(s),
          initialValue: '<p>Hello, World!</p>',
        ),
      ),
    );
  }
}

特别注意事项

  • 由于框架问题,Web平台上仅兼容Flutter 3.3及以上版本。
  • 在Android和iOS平台上,需要添加相应的权限以支持语音识别功能。
  • 在Web平台上,为了使工具栏能够水平滚动,需要覆盖默认的滚动行为。

Android权限

android/app/src/main/AndroidManifest.xml 文件中添加以下权限:

<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.BLUETOOTH" />

iOS权限

Info.plist 文件中添加以下权限:

<key>NSSpeechRecognitionUsageDescription</key>
<string>recognize speech</string>
<key>NSMicrophoneUsageDescription</key>
<string>Need microphone access for uploading videos</string>

Web平台滚动行为

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  [@override](/user/override)
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
      };
}

return MaterialApp(
  scrollBehavior: MyCustomScrollBehavior(),
  // ...
);

更多关于Flutter富文本编辑器插件flutter_rte的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter富文本编辑器插件flutter_rte的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是一个关于如何在Flutter项目中使用flutter_rte(Flutter Rich Text Editor)插件的示例代码。flutter_rte 是一个功能强大的富文本编辑器插件,支持多种文本格式和样式。

首先,确保你已经在pubspec.yaml文件中添加了flutter_rte依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_rte: ^x.y.z  # 请将 x.y.z 替换为最新版本号

然后运行 flutter pub get 来获取依赖。

接下来,在你的Flutter项目中,你可以按照以下步骤来集成和使用flutter_rte

1. 导入依赖

在你的Dart文件中导入flutter_rte

import 'package:flutter/material.dart';
import 'package:flutter_rte/flutter_rte.dart';

2. 创建编辑器屏幕

创建一个新的屏幕或页面来使用富文本编辑器。以下是一个简单的示例:

class RTEditorScreen extends StatefulWidget {
  @override
  _RTEditorScreenState createState() => _RTEditorScreenState();
}

class _RTEditorScreenState extends State<RTEditorScreen> {
  FlutterRteController _controller = FlutterRteController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter RTE Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(8.0),
        child: FlutterRte(
          controller: _controller,
          focusNode: FocusNode(), // 可以传递一个FocusNode来控制焦点
          toolbarOptions: [
            ToolbarOptions(
              iconData: Icons.format_bold,
              tooltip: 'Bold',
              onSelected: () {
                _controller.toggleBold();
              },
            ),
            ToolbarOptions(
              iconData: Icons.format_italic,
              tooltip: 'Italic',
              onSelected: () {
                _controller.toggleItalic();
              },
            ),
            // 可以添加更多ToolbarOptions,例如underline, strikethrough, link等
          ],
          initialText: '', // 初始文本内容
          // 其他配置选项,如maxHeight, readOnly等
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          // 获取编辑器内容
          _controller.getPlainText().then((text) {
            print("Editor content: $text");
            // 可以在这里处理文本内容,例如保存到数据库或进行其他操作
          });
        },
        tooltip: 'Get Text',
        child: Icon(Icons.content_copy),
      ),
    );
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
}

3. 在主应用中使用编辑器屏幕

在你的主应用文件中(例如main.dart),将编辑器屏幕添加到路由中:

import 'package:flutter/material.dart';
import 'rte_screen.dart'; // 假设你将上面的代码保存为 rte_screen.dart

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter RTE Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: RTEditorScreen(),
    );
  }
}

4. 运行应用

现在,你可以运行你的Flutter应用,应该会看到一个简单的富文本编辑器,带有加粗和斜体工具按钮,以及一个浮动操作按钮来获取编辑器内容。

这个示例展示了如何设置基本的富文本编辑器,你可以根据需要进一步自定义和扩展,例如添加更多工具栏选项、处理HTML内容等。

回到顶部