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桌面端开发------拖动文件到应用

相关推荐
ChinaDragonDreamer2 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
网络研究院4 小时前
Android 安卓内存安全漏洞数量大幅下降的原因
android·安全·编程·安卓·内存·漏洞·技术
凉亭下5 小时前
android navigation 用法详细使用
android
早起的年轻人7 小时前
Flutter String 按 ,。分割
flutter
小比卡丘7 小时前
C语言进阶版第17课—自定义类型:联合和枚举
android·java·c语言
前行的小黑炭8 小时前
一篇搞定Android 实现扫码支付:如何对接海外的第三方支付;项目中的真实经验分享;如何高效对接,高效开发
android
落落落sss9 小时前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
代码敲上天.10 小时前
数据库语句优化
android·数据库·adb
missmisslulu11 小时前
电容笔值得买吗?2024精选盘点推荐五大惊艳平替电容笔!
学习·ios·电脑·平板
GEEKVIP12 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone