flutter 长按图片保存到手机
main.dart
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:path/path.dart' as path;
import 'package:file_picker/file_picker.dart';
import 'package:permission_handler/permission_handler.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
String url = "https://i.loli.net/2020/01/14/w1dcNtf4SECG6yX.jpg";
Offset _tapPosition;
void _showCustomMenu() {
final RenderBox overlay = Overlay.of(context).context.findRenderObject();
showMenu(
context: context,
items: <PopupMenuEntry<int>>[
const PopupMenuItem<int>(
value: 1,
child: Text('Download'),
),
],
position: RelativeRect.fromRect(
_tapPosition & Size.zero, // smaller rect, the touch area
Offset.zero & overlay.size // Bigger rect, the entire screen
),
).then<void>((int r) {
if (r == null) {
print('cancel');
return;
}
if (r == 1) _download();
});
}
void _storePosition(TapDownDetails details) {
_tapPosition = details.globalPosition;
}
void _download() async {
/// 自动选择文件夹
/// /Android/data/com.<appname>/files
// final directory = await getExternalStorageDirectory();
// if (directory != null) {
// var dirPath = path.join(directory.path, "images");
// var dir = Directory(dirPath);
// await dir.create(recursive: true);
// var name = path.basename(url);
// var p = path.join(dirPath, name);
// print(p);
// await File(p).writeAsBytes(r.bodyBytes);
// print("save ok");
// }
// 1. 获取权限
var storageStatus = await Permission.storage.status;
// 没有权限则申请
if(storageStatus != PermissionStatus.granted) {
storageStatus = await Permission.storage.request();
if(storageStatus != PermissionStatus.granted) {
return;
}
}
// 2. 获取保存目录
String dpath = await FilePicker.getDirectoryPath();
print(dpath);
if (dpath != null) {
var name = path.basename(url);
var p = path.join(dpath, name);
print(p);
// 3. 从网络获取图片保存到用户手机
var r = await http.get(url);
await File(p).writeAsBytes(r.bodyBytes);
print("save ok");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: GestureDetector(
onLongPress: _showCustomMenu, // 长按打开Menu菜单
onTapDown: _storePosition, // 按下去的时候记住位置
child: Image.network(url),
),
),
);
}
}
配置权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
可能需要安装的包:
dependencies:
http:
path_provider:
path:
file_picker:
permission_handler:
flutter 长按图片保存到手机的更多相关文章
- 微信小程序base64图片保存到手机相册
问题:base64图片不能直接用wx.saveImageToPhotosAlbum保存到手机相册 解决: 先用fs.writeFile写入本地文件,再wx.saveImageToPhotosAlbum ...
- 微信小程序点击按钮将图片保存到手机
SaveCard: function(e) { let that = this; console.log('保存'); var imgSrc = e.currentTarget.dataset.img ...
- iOS,长按图片保存实现方法,轻松搞定!
1.添加手势识别: UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@s ...
- ios 点击放大图片,保存至手机相册
直接贴.m文件代码 #import "UIImageView+Scale.h" static CGRect oldframe; @implementation UIImageVie ...
- 微信APP长按图片禁止保存到本地
项目遇到一个问题,在web页面中,禁止长按图片保存, 使用css属性: img { pointer-events: none; } 或者 img { -webkit-user-select: no ...
- iOS UIWebview 长按图片,保存到本地相册
我们所要解决的问题如题目所示:ios中,长按Webview中的图片,将图片保存到本地相册.解决方案:对load的html网页,执行js注入,通过在webview中执行js代码,来响应点击事件,通过js ...
- 小程序base64图片格式保存至手机相册
// 保存图片至相册 saveImg() { //获取文件管理器对象 const fs = wx.getFileSystemManager() //文件保存路径 const Imgpath = wx. ...
- [Egret]长按图片分享、分享图片、本地存储
egret 分享有API可以把一个显示对象树渲染成一个位图纹理,我把它赋值给 HTML 的 Image 元素,就实现了图片的显示,在微信中,通过长按图片可以分享出去.当然在其他浏览器可以保存在本地. ...
- js截图及绕过服务器图片保存至本地(html2canvas)
今天要分享的是用html2canvas根据自己的需求生成截图,并且修复html2canvas截图模糊,以及绕过服务器图片保存至本地. 只需要短短的几行代码,就能根据所需的dom截图,是不是很方便,但是 ...
随机推荐
- 像羽毛一样轻的MVVMLight(一)(MVVM 和 MVVMLight简介)
致敬 在此致敬翁智华大佬,感谢大佬为后辈们写下如此详细的文档,本文将在原文基础上添加些自己的理解,希望这样优秀的文档广为流传. 原文请参考 https://www.cnblogs.com/wzh201 ...
- BIO,NIO,AIO 总结
BIO,NIO,AIO 总结 Java 中的 BIO.NIO和 AIO 理解为是 Java 语言对操作系统的各种 IO 模型的封装.程序员在使用这些 API 的时候,不需要关心操作系统层面的知识,也不 ...
- IntelliJ Idea 解决 Could not autowire. No beans of 'xxxx' type found 的错误提示
IntelliJ Idea 解决 Could not autowire. No beans of 'xxxx' type found 的错误提示哈,在使用 @Autowired 时,今天又遇一坑,这俩 ...
- Language Guide (proto3) | proto3 语言指南(十)映射
Maps - 映射 如果要创建关联映射作为数据定义的一部分,协议缓冲区提供了一种方便的快捷语法: map<key_type, value_type> map_field = N; -其中k ...
- 静默安装Oracle也没那么恐怖
几种必须静默安装的情况 服务器为了减少资源占用,没安装图形组件 不能进入机房,只能远程SSH 想炫(Z)耀(B),静默安装显得有技术含量 磁盘分区要求 如没有特别要求,装机时可按如下分区比较好管理 / ...
- Java中把对象、对象bean、list集合、对象数组、Map和Set以及字符串转换成Json
对象转换为Json 对象bean转换为Json List集合转换为Json 对象数组转换为Json Map集合转换为Json Set集合转为Json 字符串转换为Json 把Java对常用的一些数据转 ...
- Spring boot 异步线程池
package com.loan.msg.config; import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandle ...
- Dubbo官网实战使用技巧
原文链接:Dubbo官网实战使用技巧 1.启动时检查: 我们检查依赖的服务是否启动,可利用下面三个属性,优先级从左到右逐渐降低. 如果服务不是强依赖,或者说服务之间可能存在死循环依赖,我们应该将 ch ...
- jackson学习之七:常用Field注解
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- P1091 合唱队形(LIS)
题目描述 NNN位同学站成一排,音乐老师要请其中的(N−KN-KN−K)位同学出列,使得剩下的KKK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,-,K1,2, ...