Flutter桌面端-选取和拖动本地文件到应用

前言

Flutter桌面端应用经常需要选取本地文件进行处理。选取文件的方式主要有两种,

  1. 直接将文件拖动到应用中
  2. 弹出一个文件浏览器来选取文件。

实现拖动文件到应用

目前Flutter实现拖动文件到应用的功能主要是使用 desktop_drop 插件。
desktop_drop插件的使用比较简单。

  • 1.导入 desktop_drop 库。
    添加 desktop_drop 到pubspec.yaml文件中 desktop_drop: ^0.4.1
  • 2.在需要处理文件拖动的widget上面加上 DropTarget
  • 3.在 DropTargetonDragDone 回调里面获取文件路径

以下为示例代码

dart 复制代码
    // 使用DropTarget包裹之后该widget区域可以检测到文件拖放
    DropTarget(
      // onDragDone拖放完成后会回调
      onDragDone: (DropDoneDetails details) {
        // details.files为List<XFile>类型,因为一次可以拖动多个文件,所以是一个数组
        // details.files.last.path 本Demo中我们只获取最后一个文件的路径
        debugPrint("onDragDone details=${details.files}");
        // 获取到文件路径
        String? path = details.files.last.path;
        debugPrint("path=$path");
        setState(() {
          // 在界面上显示文件路径
          _filePath = details.files.last.path;
        });
      },
      child: SizedBox(
        width: 600,
        height: 100,
        // DottedBorder虚线框
        child: DottedBorder(
          borderType: BorderType.RRect,
          radius: const Radius.circular(10),
          color: Colors.blue,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                _filePath != null
                    ? Text(_filePath!)
                    : const Text("拖动文件到此处"),
              ],
            ),
          ),
        ),
      ),
    ),

示例代码中,我们使用DottedBorder构建了一个方形的虚线框,然后在DottedBorder上面添加了DropTarget来处理拖动事件。在onDragDone回调里面通过 details.files.last.path 获取到文件路径,然后将文件路径显示出来。获取到文件路径之后,我们就可以做很多事情了,比如读取文件内容,读取文件大小、拷贝文件等等。

通过文件浏览器选取本地文件

通过弹出一个文件浏览器(MacOS上是Finder)的方式来选取文件是最常用的一种方式了(虽然我觉得没有拖动文件选取好用)。

目前选取文件也是通过插件,用的比较多的插件有 file_selectorfile_picker

虽然 file_selector 是Flutter官方维护的,但是不管是便捷度和功能被 file_picker 吊打,所以大部分人都选择使用 file_picker

file_picker的使用也不复杂

  • 1.导入 file_picker 库。
    添加 file_pickerpubspec.yaml 文件中。file_picker: ^5.0.2
  • 2.在一个Button点击事件上调用 FilePicker.platform.pickFiles() 方法
  • 3.等待 pickFiles 方法的结果,在结果里面获取到用户选择的文件路径
    String? path = result.files.last.path;

以下为示例代码

dart 复制代码
ElevatedButton(
  onPressed: () async {
    FilePickerResult? result = await FilePicker.platform.pickFiles(
      // 文件浏览器的标题,可不设置
      dialogTitle: "请选择文件",
      // 初始化路径,默认是上一次打开的路径。设置了则打开指定的文件夹路径。Windows系统该参数无效
      // initialDirectory:
      //     (await getApplicationDocumentsDirectory()).path,
      initialDirectory: "/Users/sandershi/Desktop/test",
      // 文件类型,默认为FileType.any,允许任何文件。设置成custom后,可以配合allowedExtensions实现只选取指定后缀的文件
      type: FileType.custom,
      // 允许的扩展名,仅在type为custom时使用,只允许选取指定扩展名的文件
      allowedExtensions: ["log", "apk"],
      // 允许多选,默认为false,每次只选择一个文件。设置为true则允许一次选择多个文件
      allowMultiple: false,
    );
    if (result != null) {
      String? path = result.files.last.path;
      debugPrint("已选取文件 path=$path");
      setState(() {
        _selectFilePath = path;
      });
    } else {
      debugPrint("取消选取");
    }
  },
  child: const Text("点击选取文件"),
),
const SizedBox(height: 10),
if (_selectFilePath != null) Text("$_selectFilePath"),

示例代码中我们在点击ElevatedButton的时候调用了 await FilePicker.platform.pickFiles来弹出文件选择框 ,然后等待结果,若 result 不为空 ,代表用户选择了文件,则从 result.files 里面选择最后的一个文件的路径,显示到界面上。

值得一说的是pickFiles方法有很多参数,桌面端常用的几个参数都在代码里面注释了。所有参数都可以不加,默认就是选择一个文件。

文件选取最佳实践:拖动+点击选取结合

我们上面讲解了拖动文件到应用和弹出文件浏览器让用户选择文件的方案,那么选择文件的最佳实践就很容易实现了。

文件选取最佳实践:显示一个虚线框,用户可以拖动文件到这个虚线框区域内,也可以直接点击虚线框区域弹出文件浏览器来选择文件。

实现方案就是在原先拖动文件到应用的示例代码中,加上GestrueDetector的点击手势,点击后调用 file_picker 的选择文件方法。

dart 复制代码
// 使用DropTarget包裹之后该widget区域可以检测到文件拖放
DropTarget(
  // onDragDone 拖放完成后会回调
  onDragDone: (DropDoneDetails details) {
    debugPrint("onDragDone details=${details.files}");
    // 获取到文件路径
    String? path = details.files.last.path;
    debugPrint("path=$path");
    setState(() {
      _filePath = details.files.last.path;
    });
  },
  // 拖动到指定区域时回调
  onDragEntered: (DropEventDetails details) {
    setState(() {
      _isDragging = true;
    });
  },
  // 离开指定区域时回调
  onDragExited: (DropEventDetails details) {
    setState(() {
      _isDragging = false;
    });
  },
  child: GestureDetector(
    // GestureDetector onTap 点击选线区域调用pickFiles方法来选取文件
    onTap: () async {
      FilePickerResult? result =
          await FilePicker.platform.pickFiles(
        initialDirectory: "/Users/sandershi/Desktop/test",
      );
      if (result != null) {
        String? path = result.files.last.path;
        debugPrint("已选取文件 path=$path");
        setState(() {
          _filePath = path;
        });
      } else {
        debugPrint("取消选取");
      }
    },
    child: SizedBox(
      width: 600,
      height: 100,
      // 虚线框
      child: DottedBorder(
        borderType: BorderType.RRect,
        radius: const Radius.circular(10),
        color: _isDragging ? Colors.orange : Colors.blue,
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              _filePath != null
                  ? Text(_filePath!)
                  : const Text("拖动文件到此处或点击选取文件"),
            ],
          ),
        ),
      ),
    ),
  ),
),

总结

Flutter桌面端应用可以通过 desktop_drop 插件实现拖动文件到应用的功能,通过 file_picker 插件实现点击弹出文件浏览器选取文件的功能。

文件选取最佳实践是显示一个虚线框,可以拖动文件到虚线框中实现文件选取,也可以通过点击虚线框弹出文件浏览器来选取文件。

参考

desktop_drop file_picker dotted_border虚线框
file_picker官方文档
Flutter桌面端开发------选择读取本地文件
Flutter桌面端开发------拖动文件到应用

相关推荐
微祎_43 分钟前
Flutter for OpenHarmony:构建一个 Flutter 平衡球游戏,深入解析动画控制器、实时物理模拟与手势驱动交互
flutter·游戏·交互
ZH15455891312 小时前
Flutter for OpenHarmony Python学习助手实战:面向对象编程实战的实现
python·学习·flutter
renke33643 小时前
Flutter for OpenHarmony:构建一个 Flutter 色彩调和师游戏,RGB 空间探索、感知色差计算与视觉认知训练的工程实现
flutter·游戏
游戏开发爱好者83 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码20353 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥3 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓3 小时前
[JDBC]元数据
android
独行soc3 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能4 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿4 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市