Flutter桌面端-选取和拖动本地文件到应用
前言
Flutter桌面端应用经常需要选取本地文件进行处理。选取文件的方式主要有两种,
- 直接将文件拖动到应用中
- 弹出一个文件浏览器来选取文件。
实现拖动文件到应用
目前Flutter实现拖动文件到应用的功能主要是使用 desktop_drop 插件。
desktop_drop
插件的使用比较简单。
- 1.导入
desktop_drop
库。 添加desktop_drop
到pubspec.yaml文件中desktop_drop: ^0.4.1
- 2.在需要处理文件拖动的widget上面加上
DropTarget
- 3.在
DropTarget
的onDragDone
回调里面获取文件路径
以下为示例代码
// 使用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_selector 和 file_picker 。
虽然 file_selector
是Flutter官方维护的,但是不管是便捷度和功能被 file_picker
吊打,所以大部分人都选择使用 file_picker
。
file_picker
的使用也不复杂
- 1.导入
file_picker
库。 添加file_picker
到pubspec.yaml
文件中。file_picker: ^5.0.2
- 2.在一个Button点击事件上调用
FilePicker.platform.pickFiles()
方法 - 3.等待 pickFiles 方法的结果,在结果里面获取到用户选择的文件路径
String? path = result.files.last.path;
以下为示例代码
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
的选择文件方法。
// 使用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
插件实现点击弹出文件浏览器选取文件的功能。
文件选取最佳实践是显示一个虚线框,可以拖动文件到虚线框中实现文件选取,也可以通过点击虚线框弹出文件浏览器来选取文件。
参考
转载自:https://juejin.cn/post/7287783890512674853