Flutter文本编辑增强插件flow_compose的使用

Flutter文本编辑增强插件flow_compose的使用

本文将介绍如何使用Flutter中的文本编辑增强插件flow_compose。此插件旨在帮助构建AI代理或其他流程图工具。

插件功能概述

flow_compose插件可以帮助开发者轻松地在Flutter应用中实现复杂的流程图编辑功能。通过这个插件,你可以创建可交互的流程图,并且能够动态添加、删除节点和边。

示例代码

以下是一个完整的示例代码,展示了如何使用flow_compose插件来创建一个简单的流程图编辑器。

import 'dart:convert';

import 'package:example/nodes/sql_node.dart';
import 'package:example/style.dart';
import 'package:example/workflow/workflow_graph.dart';
import 'package:flow_compose/flow_compose.dart';
import 'package:flutter/material.dart';
import 'package:flutter_expandable_fab/flutter_expandable_fab.dart';
import 'package:flutter_json_view/flutter_json_view.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:toastification/toastification.dart';

import 'nodes/login_node.dart';
import 'nodes/simple_qa_node.dart';
import 'nodes/start_node.dart';
import 'workflow/workflow_notifier.dart';

void main() {
  runApp(ToastificationWrapper(
    child: ProviderScope(child: MyApp()),
  ));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends ConsumerStatefulWidget {
  const MyHomePage({super.key, required this.title});
  final String title;

  @override
  ConsumerState<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends ConsumerState<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    final controller = ref.read(workflowProvider.notifier).controller;
    return Scaffold(
      body: InfiniteDrawingBoard(
        controller: controller,
      ),
      floatingActionButtonLocation: ExpandableFab.location,
      floatingActionButton: ExpandableFab(
        distance: 50,
        type: ExpandableFabType.up,
        children: [
          FloatingActionButton.small(
            tooltip: "重新居中",
            heroTag: null,
            child: const Icon(Icons.center_focus_strong),
            onPressed: () {
              controller.reCenter();
            },
          ),
          FloatingActionButton.small(
            tooltip: "清除",
            heroTag: null,
            child: const Icon(Icons.clear_all),
            onPressed: () {
              controller.clear();
            },
          ),
          FloatingActionButton.small(
            tooltip: "执行",
            heroTag: null,
            child: const Icon(Icons.start),
            onPressed: () {
              WorkflowGraph graph = WorkflowGraph(controller.state.value.data,
                  controller.state.value.edges.toList());

              Future.microtask(() async {
                graph.executeWorkflow(ref);
              });
            },
          ),
          FloatingActionButton.small(
            tooltip: "从JSON导入",
            heroTag: null,
            child: const Icon(Icons.edit),
            onPressed: () {
              final textController = TextEditingController();
              showGeneralDialog(
                  barrierDismissible: true,
                  barrierLabel: "json",
                  context: context,
                  pageBuilder: (c, _, __) {
                    return Center(
                      child: Material(
                        borderRadius: BorderRadius.circular(20),
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          width: 600,
                          height: 400,
                          child: TextField(
                            controller: textController,
                            decoration: inputDecoration,
                            maxLines: 20,
                          ),
                        ),
                      ),
                    );
                  }).then((_) {
                if (textController.text.isNotEmpty) {
                  Map<String, dynamic> data = jsonDecode(textController.text);
                  List<INode> nodes = [];
                  List<Edge> edges = [];
                  for (var node in data["nodes"]) {
                    // nodes.add(INode.fromJson(node));
                    if (node['builderName'] == "StartNode") {
                      nodes.add(StartNode.fromJson(node));
                    } else if (node['builderName'] == "SqlNode") {
                      nodes.add(SqlNode.fromJson(node));
                    } else if (node['builderName'] == "SimpleQaNode") {
                      nodes.add(SimpleQaNode.fromJson(node));
                    } else if (node['builderName'] == "LoginNode") {
                      nodes.add(LoginNode.fromJson(node));
                    } else {
                      nodes.add(INode.fromJson(node));
                    }
                  }
                  for (var edge in data["edges"]) {
                    edges.add(Edge.fromJson(edge));
                  }

                  controller.reCreate(nodes, edges);
                }
              });
            },
          ),
          FloatingActionButton.small(
            tooltip: "导出为JSON",
            heroTag: null,
            child: const Icon(Icons.abc),
            onPressed: () {
              debugPrint(controller.dumpToString());
              showGeneralDialog(
                  barrierDismissible: true,
                  barrierLabel: "json",
                  context: context,
                  pageBuilder: (c, _, __) {
                    return Center(
                      child: Material(
                        borderRadius: BorderRadius.circular(20),
                        child: Container(
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                          ),
                          width: 600,
                          height: 400,
                          child: JsonView.string(controller.dumpToString()),
                        ),
                      ),
                    );
                  });
            },
          ),
        ],
      ),
    );
  }
}

功能说明

1. 重新居中 (reCenter)

点击此按钮可以将整个流程图重新居中到屏幕中央。

FloatingActionButton.small(
  tooltip: "重新居中",
  heroTag: null,
  child: const Icon(Icons.center_focus_strong),
  onPressed: () {
    controller.reCenter();
  },
)

2. 清除 (clear)

点击此按钮可以清除所有已添加的节点和边。

FloatingActionButton.small(
  tooltip: "清除",
  heroTag: null,
  child: const Icon(Icons.clear_all),
  onPressed: () {
    controller.clear();
  },
)

3. 执行 (execute)

点击此按钮可以执行当前的流程图。

FloatingActionButton.small(
  tooltip: "执行",
  heroTag: null,
  child: const Icon(Icons.start),
  onPressed: () {
    WorkflowGraph graph = WorkflowGraph(controller.state.value.data,
        controller.state.value.edges.toList());

    Future.microtask(() async {
      graph.executeWorkflow(ref);
    });
  },
)

4. 从JSON导入 (fromJson)

点击此按钮可以导入一个JSON文件来重新创建当前的流程图。

FloatingActionButton.small(
  tooltip: "从JSON导入",
  heroTag: null,
  child: const Icon(Icons.edit),
  onPressed: () {
    final textController = TextEditingController();
    showGeneralDialog(
        barrierDismissible: true,
        barrierLabel: "json",
        context: context,
        pageBuilder: (c, _, __) {
          return Center(
            child: Material(
              borderRadius: BorderRadius.circular(20),
              child: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(20),
                ),
                width: 600,
                height: 400,
                child: TextField(
                  controller: textController,
                  decoration: inputDecoration,
                  maxLines: 20,
                ),
              ),
            ),
          );
        }).then((_) {
      if (textController.text.isNotEmpty) {
        Map<String, dynamic> data = jsonDecode(textController.text);
        List<INode> nodes = [];
        List<Edge> edges = [];
        for (var node in data["nodes"]) {
          if (node['builderName'] == "StartNode") {
            nodes.add(StartNode.fromJson(node));
          } else if (node['builderName'] == "SqlNode") {
            nodes.add(SqlNode.fromJson(node));
          } else if (node['builderName'] == "SimpleQaNode") {
            nodes.add(SimpleQaNode.fromJson(node));
          } else if (node['builderName'] == "LoginNode") {
            nodes.add(LoginNode.fromJson(node));
          } else {
            nodes.add(INode.fromJson(node));
          }
        }
        for (var edge in data["edges"]) {
          edges.add(Edge.fromJson(edge));
        }

        controller.reCreate(nodes, edges);
      }
    });
  },
)

5. 导出为JSON (toJson)

点击此按钮可以将当前的流程图导出为JSON格式。

FloatingActionButton.small(
  tooltip: "导出为JSON",
  heroTag: null,
  child: const Icon(Icons.abc),
  onPressed: () {
    debugPrint(controller.dumpToString());
    showGeneralDialog(
        barrierDismissible: true,
        barrierLabel: "json",
        context: context,
        pageBuilder: (c, _, __) {
          return Center(
            child: Material(
              borderRadius: BorderRadius.circular(20),
              child: Container(
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(20),
                ),
                width: 600,
                height: 400,
                child: JsonView.string(controller.dumpToString()),
              ),
            ),
          );
        });
  },
)

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

1 回复

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


flow_compose 是一个用于 Flutter 的文本编辑增强插件,它允许开发者通过组合式的方式来构建复杂的文本编辑功能。这个插件的设计灵感来自于 Jetpack Compose,它提供了一种声明式的方式来处理文本编辑和输入。

安装

首先,你需要在 pubspec.yaml 文件中添加 flow_compose 依赖:

dependencies:
  flutter:
    sdk: flutter
  flow_compose: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来安装依赖。

基本用法

flow_compose 的核心是 FlowCompose 组件,它可以用来包裹你的文本编辑控件,并通过组合不同的 FlowComposeNode 来实现文本编辑的增强功能。

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

class MyTextEditor extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('FlowCompose Example'),
      ),
      body: FlowCompose(
        child: TextField(
          decoration: InputDecoration(
            hintText: 'Type something...',
          ),
        ),
        nodes: [
          // 添加一些节点来增强文本编辑功能
          FlowComposeNode(
            condition: (text) => text.contains('@'),
            action: (text, selection) {
              // 当检测到 '@' 时,触发某些操作
              print('Detected @ in text: $text');
            },
          ),
          FlowComposeNode(
            condition: (text) => text.length > 10,
            action: (text, selection) {
              // 当文本长度超过 10 时,触发某些操作
              print('Text length exceeds 10 characters');
            },
          ),
        ],
      ),
    );
  }
}

节点(Nodes)

FlowComposeNodeflow_compose 的核心概念。每个节点包含一个 condition 和一个 action

  • condition: 一个函数,接受当前文本作为参数,返回一个布尔值。当条件为 true 时,action 会被触发。
  • action: 一个函数,接受当前文本和选择范围作为参数,执行某些操作。

自定义节点

你可以根据需要创建自定义的 FlowComposeNode 来实现特定的文本编辑逻辑。例如,你可以创建一个节点来检测特定的关键词并执行相应的操作。

FlowComposeNode(
  condition: (text) => text.contains('flutter'),
  action: (text, selection) {
    // 当检测到 'flutter' 时,触发某些操作
    print('Flutter mentioned!');
  },
);

高级用法

flow_compose 还支持更高级的用法,例如组合多个节点、动态添加和删除节点等。你可以通过 FlowComposeController 来更精细地控制文本编辑的行为。

FlowComposeController _controller = FlowComposeController();

[@override](/user/override)
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Advanced FlowCompose Example'),
    ),
    body: FlowCompose(
      controller: _controller,
      child: TextField(
        decoration: InputDecoration(
          hintText: 'Type something...',
        ),
      ),
      nodes: [
        // 初始节点
        FlowComposeNode(
          condition: (text) => text.contains('@'),
          action: (text, selection) {
            print('Detected @ in text: $text');
          },
        ),
      ],
    ),
    floatingActionButton: FloatingActionButton(
      onPressed: () {
        // 动态添加节点
        _controller.addNode(
          FlowComposeNode(
            condition: (text) => text.contains('#'),
            action: (text, selection) {
              print('Detected # in text: $text');
            },
          ),
        );
      },
      child: Icon(Icons.add),
    ),
  );
}
回到顶部