Flutter文本编辑器

举报
坚果的博客 发表于 2022/07/29 08:00:41 2022/07/29
【摘要】 最近项目里要用到图文编辑,于是寻找技术方案在这儿,我也是找到了一个不错的插件,分享给大家,地址介绍Flutter HTML Editor Enhanced 是一款适用于 Android、iOS 和 Web 的文本编辑器,可帮助大家编写所见即所得的 HTML 代码。在线API 参考安装方式一:运行此命令: flutter pub add html_editor_enhanced这将在你的包的...

最近项目里要用到图文编辑,于是寻找技术方案

在这儿,我也是找到了一个不错的插件,分享给大家,

地址

介绍

Flutter HTML Editor Enhanced 是一款适用于 Android、iOS 和 Web 的文本编辑器,可帮助大家编写所见即所得的 HTML 代码。在线API 参考

安装


方式一:运行此命令:

  flutter pub add html_editor_enhanced

这将在你的包的 pubspec.yaml 中添加这样的一行(并运行一个隐式flutter pub get):

或者直接在pubspec.yaml 中添加之后,


dependencies:
  html_editor_enhanced: ^2.5.0

运行

image-20220728075955734

、或者,您的编辑器可能支持flutter pub get. 检查您的编辑器的文档以了解更多信息。

导入它

现在在您的 Dart 代码中,您可以使用:

import 'package:html_editor_enhanced/html_editor.dart';
import 'package:html_editor_enhanced/utils/callbacks.dart';
import 'package:html_editor_enhanced/utils/file_upload_model.dart';
import 'package:html_editor_enhanced/utils/options.dart';
import 'package:html_editor_enhanced/utils/plugins.dart';
import 'package:html_editor_enhanced/utils/shims/dart_ui.dart';
import 'package:html_editor_enhanced/utils/shims/dart_ui_fake.dart';
import 'package:html_editor_enhanced/utils/shims/dart_ui_real.dart';
import 'package:html_editor_enhanced/utils/shims/flutter_inappwebview_fake.dart';
import 'package:html_editor_enhanced/utils/toolbar.dart';
import 'package:html_editor_enhanced/utils/utils.dart';


最简单的使用

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:html_editor_enhanced/html_editor.dart';
import 'package:file_picker/file_picker.dart';
​
void main() => runApp(HtmlEditorExampleApp());
​
class HtmlEditorExampleApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(),
      darkTheme: ThemeData.dark(),
      home: HtmlEditorExample(title: '大前端之旅'),
    );
  }
}
​
class HtmlEditorExample extends StatefulWidget {
  HtmlEditorExample({Key? key, required this.title}) : super(key: key);
​
  final String title;
​
  @override
  _HtmlEditorExampleState createState() => _HtmlEditorExampleState();
}
​
class _HtmlEditorExampleState extends State<HtmlEditorExample> {
  String result = '';
  final HtmlEditorController controller = HtmlEditorController();
​
  @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,
                  //initialText: "<p>text content initial, if any</p>",
                ),
                htmlToolbarOptions: HtmlToolbarOptions(
                  toolbarPosition: ToolbarPosition.custom, //by default
                  // toolbarType: ToolbarType.nativeExpandable, //
                  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: 700),
                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');
                }),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor: Colors.blueGrey),
                      onPressed: () {
                        controller.clear();
                      },
                      child: Text('清空', 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(
                        '提交',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                    SizedBox(
                      width: 16,
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor:
                              Theme.of(context).colorScheme.secondary),
                      onPressed: () {
                        controller.insertText('Google');
                      },
                      child: Text('插入', style: TextStyle(color: Colors.white)),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    Text(
                      result,
                      style: TextStyle(color: Colors.white),
                    ),
                    TextButton(
                      style: TextButton.styleFrom(
                          backgroundColor:
                              Theme.of(context).colorScheme.secondary),
                      onPressed: () {
                        controller.insertNetworkImage(
                            'https://luckly007.oss-cn-beijing.aliyuncs.com/macimages/image-20220713142248972.png',
                            filename: 'network image');
                      },
                      child: Text(
                        '插入图片',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
​



​
class descTitleWidget extends StatelessWidget {
  const descTitleWidget({
    Key? key,
    required this.submit,
  }) : super(key: key);
​
  final String submit;
​
  @override
  Widget build(BuildContext context) {
    return Container(
      decoration: new BoxDecoration(
        //背景
        color: Color(0xFFF6F6F6),
        //设置四周圆角 角度
​
        borderRadius: BorderRadius.only(
            topLeft: Radius.circular(24.w), topRight: Radius.circular(24.w)),
        //设置四周边框
        border: new Border.all(width: 1.w, color: Color(0x99CFD3E6)),
      ),
      height: 96.w,
      padding: EdgeInsets.only(
          left: 28.w,
          // top: 32.w,
          right: 28.w),
      width: MediaQuery.of(context).size.width,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Text(
            submit,
            style: currentTheme.ctd.subTitle * currentTheme.ctd.txtBlack,
          ),
          Row(
            children: [
              SizedBox(
                width: 124.w,
                height: 52.w,
                child: TextButton.icon(
                    onPressed: () async {
                      // var clipboardData = await Clipboard
                      //     .getData(Clipboard
                      //         .kTextPlain); //获取粘贴板中的文本
                      // if (clipboardData != null)
                      //   _clipBoardData =
                      //       clipboardData.text!;
                      // else
                      //   _clipBoardData = "";
                      // int start = _quillController!
                      //     .selection.start;
                      // _quillController!.document.insert(
                      //     start, _clipBoardData);
​
                      // refreshUI();
                    },
                    style: TextButton.styleFrom(
                      padding: EdgeInsets.zero,
                      primary: Colors.white,
                      backgroundColor: Colors.white,
                      textStyle: TextStyle(fontSize: 20.w),
                      shape: RoundedRectangleBorder(
                          borderRadius:
                              BorderRadius.all(Radius.circular(40.w))),
                    ),
                    icon: Image.asset("images/circle-icon-paste.png"),
                    label: Text("粘贴",
                        style: TextStyle(
                          fontSize: 20.w,
                          color: Color_TitleBlack,
                        ))),
              ),
              SizedBox(width: 10.w),
              SizedBox(
                width: 124.w,
                height: 52.w,
                child: TextButton.icon(
                    onPressed: () {
                      // _picPicker();
                    },
                    style: TextButton.styleFrom(
                      padding: EdgeInsets.zero,
                      primary: Colors.white,
                      backgroundColor: Colors.white,
                      textStyle: TextStyle(fontSize: 20.w),
                      shape: RoundedRectangleBorder(
                          borderRadius:
                              BorderRadius.all(Radius.circular(40.w))),
                    ),
                    icon: Image.asset("images/circle-icon-album.png"),
                    label: Text("插图",
                        style: TextStyle(
                          fontSize: 20.w,
                          color: Color_TitleBlack,
                        ))),
              ),
            ],
          ),
        ],
      ),
    );
  }
}
​
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。