Flutter故事编辑器插件flutter_story_editor的使用

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

Flutter故事编辑器插件flutter_story_editor的使用

简介

flutter_story_editor 是一个基于 WhatsApp 故事风格的图片和视频编辑器插件,允许用户同时编辑图片和视频。你可以添加文本、贴纸、自由手绘、应用滤镜,并且支持撤销操作。编辑后的图片将通过 onSave 回调返回为 List<File>,你可以将其上传到存储或保存到本地相册。

功能

  • ✅ 编辑图片和视频
  • ✅ 可拖动的花哨文本(自定义颜色、字体、调整大小)
  • ✅ 可拖动的贴纸和表情符号
  • ✅ 应用滤镜到图片
  • ✅ 在图片上自由手绘
  • ✅ 剪辑视频帧

未来功能

  • 🚀 在视频帧上绘制绘画(需要平台特定的工作)
  • 🚀 更多图片和视频编辑功能(如 WhatsApp 和 Instagram 故事)
  • 🚀 UI 目前类似 WhatsApp,但可以设计独特的 Flutter 风格(欢迎贡献和建议)
  • 🚀 改善和增强性能及现有功能

插件演示

演示1 演示2 演示3

安装

1. 添加依赖

pubspec.yaml 文件中添加 flutter_story_editor

dependencies:
  flutter_story_editor: latest_version

然后导入插件:

import 'package:flutter_story_editor/flutter_story_editor.dart';
2. Android 配置

AndroidManifest.xml 文件中添加以下代码:

<activity
    android:name="com.yalantis.ucrop.UCropActivity"
    android:screenOrientation="portrait"
    android:theme="@style/Theme.AppCompat.Light.NoActionBar"/>
3. iOS 配置

info.plist 文件中添加以下代码:

<key>NSCameraUsageDescription</key>
<string>用于演示图像选择插件</string>
<key>NSMicrophoneUsageDescription</key>
<string>用于捕捉音频以供图像选择插件使用</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>用于演示图像选择插件</string>

使用方法

1. 初始化控制器

StatefulWidgetState 中初始化控制器:

FlutterStoryEditorController controller = FlutterStoryEditorController();
final TextEditingController _captionController = TextEditingController();
2. 选择媒体文件

创建一个方法来选择媒体文件(图片和视频):

List<File>? _selectedMedia;
List<String>? _mediaTypes; // 用于存储每个选定文件的类型

Future<void> selectMedia() async {
  setState(() {
    _selectedMedia = null;
    _mediaTypes = null;
  });

  try {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.media,
      allowMultiple: true,
    );
    if (result != null) {
      _selectedMedia = result.files.map((file) => File(file.path!)).toList();

      // 初始化媒体类型列表
      _mediaTypes = List<String>.filled(_selectedMedia!.length, '');

      // 确定每个选定文件的类型
      for (int i = 0; i < _selectedMedia!.length; i++) {
        String extension = path.extension(_selectedMedia![i].path).toLowerCase();
        if (extension == '.jpg' || extension == '.jpeg' || extension == '.png') {
          _mediaTypes![i] = 'image';
        } else if (extension == '.mp4' || extension == '.mov' || extension == '.avi') {
          _mediaTypes![i] = 'video';
        }
      }

      setState(() {});
    }
  } catch (e) {
    throw Exception("无法选择文件,请重试");
  }
}
3. 显示编辑器

在选择媒体文件后,显示 FlutterStoryEditor 编辑器:

selectMedia().then((value) {
  if (_selectedMedia != null && _selectedMedia!.isNotEmpty) {
    showModalBottomSheet(
      isScrollControlled: true,
      isDismissible: false,
      enableDrag: false,
      context: context,
      builder: (context) {
        return FlutterStoryEditor(
          controller: controller,
          captionController: _captionController,
          selectedFiles: _selectedMedia,
          onSaveClickListener: (files) {
            // 这里处理编辑后的文件
          },
        );
      },
    );
  }
});
4. 完整示例代码
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter_story_editor/flutter_story_editor.dart';
import 'package:path/path.dart' as path;

class FlutterStoryEditorExample extends StatefulWidget {
  const FlutterStoryEditorExample({super.key});

  [@override](/user/override)
  State<FlutterStoryEditorExample> createState() => _FlutterStoryEditorExampleState();
}

class _FlutterStoryEditorExampleState extends State<FlutterStoryEditorExample> with SingleTickerProviderStateMixin {

  FlutterStoryEditorController controller = FlutterStoryEditorController();
  final TextEditingController _captionController = TextEditingController();

  List<File>? _selectedMedia;
  List<String>? _mediaTypes; // 用于存储每个选定文件的类型

  Future<void> selectMedia() async {
    setState(() {
      _selectedMedia = null;
      _mediaTypes = null;
    });

    try {
      final result = await FilePicker.platform.pickFiles(
        type: FileType.media,
        allowMultiple: true,
      );
      if (result != null) {
        _selectedMedia = result.files.map((file) => File(file.path!)).toList();

        // 初始化媒体类型列表
        _mediaTypes = List<String>.filled(_selectedMedia!.length, '');

        // 确定每个选定文件的类型
        for (int i = 0; i < _selectedMedia!.length; i++) {
          String extension = path.extension(_selectedMedia![i].path).toLowerCase();
          if (extension == '.jpg' || extension == '.jpeg' || extension == '.png') {
            _mediaTypes![i] = 'image';
          } else if (extension == '.mp4' || extension == '.mov' || extension == '.avi') {
            _mediaTypes![i] = 'video';
          }
        }

        setState(() {});
      }
    } catch (e) {
      throw Exception("无法选择文件,请重试");
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Center(
            child: IconButton(
              onPressed: () {
                selectMedia().then((value) {
                  if (_selectedMedia != null && _selectedMedia!.isNotEmpty) {
                    showModalBottomSheet(
                      isScrollControlled: true,
                      isDismissible: false,
                      enableDrag: false,
                      context: context,
                      builder: (context) {
                        return FlutterStoryEditor(
                          controller: controller,
                          captionController: _captionController,
                          selectedFiles: _selectedMedia,
                          onSaveClickListener: (files) {
                            // 这里处理编辑后的文件
                          },
                        );
                      },
                    );
                  }
                });
              },
              icon: const Icon(Icons.upload, size: 50),
            ),
          ),
          const SizedBox(height: 10),
          const Text("选择文件并进行编辑"),
        ],
      ),
    );
  }
}

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

1 回复

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


当然,以下是如何在Flutter项目中集成和使用flutter_story_editor插件的一个基本示例。这个插件假设是用于创建一个故事编辑器,但请注意,由于这是一个假定的插件(因为实际上可能不存在一个名为flutter_story_editor的官方或广泛使用的插件),我将基于一般的Flutter插件集成步骤来提供一个示例代码框架。

首先,确保你的Flutter环境已经设置好,并且你的项目已经初始化。

1. 添加依赖

在你的pubspec.yaml文件中添加flutter_story_editor作为依赖项(注意:这里flutter_story_editor是假设的,实际使用时请替换为真实插件名):

dependencies:
  flutter:
    sdk: flutter
  flutter_story_editor: ^x.y.z  # 替换为实际版本号

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

2. 导入插件

在你的Dart文件中(例如main.dart),导入插件:

import 'package:flutter/material.dart';
import 'package:flutter_story_editor/flutter_story_editor.dart';  // 假设的导入路径

3. 使用插件

在你的Flutter应用中创建一个页面来使用flutter_story_editor插件。下面是一个简单的示例,展示如何在一个页面中集成故事编辑器:

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

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

class StoryEditorPage extends StatefulWidget {
  @override
  _StoryEditorPageState createState() => _StoryEditorPageState();
}

class _StoryEditorPageState extends State<StoryEditorPage> {
  // 假设的故事数据
  String storyContent = "这是一个故事的开始...";

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('故事编辑器'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // 使用假设的StoryEditor组件
            FlutterStoryEditor(
              initialContent: storyContent,
              onChanged: (newContent) {
                setState(() {
                  storyContent = newContent;
                });
              },
            ),
            SizedBox(height: 20),
            // 显示当前故事内容的Text组件
            Text(
              "当前故事内容:\n$storyContent",
              style: TextStyle(fontSize: 16),
            ),
          ],
        ),
      ),
    );
  }
}

注意事项

  1. 插件实际存在性:请注意,flutter_story_editor是一个假设的插件名。在实际使用中,你需要替换为真实存在的插件名。
  2. 插件文档:在集成任何第三方插件时,请务必阅读其官方文档,了解如何正确配置和使用。
  3. 错误处理:在实际应用中,你可能需要添加更多的错误处理和用户交互逻辑。

希望这个示例能帮助你理解如何在Flutter项目中集成和使用一个假设的故事编辑器插件。如果你有一个具体的插件名称或更多的需求,请提供详细信息,以便给出更准确的指导。

回到顶部