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 长按图片保存到手机的更多相关文章

  1. 微信小程序base64图片保存到手机相册

    问题:base64图片不能直接用wx.saveImageToPhotosAlbum保存到手机相册 解决: 先用fs.writeFile写入本地文件,再wx.saveImageToPhotosAlbum ...

  2. 微信小程序点击按钮将图片保存到手机

    SaveCard: function(e) { let that = this; console.log('保存'); var imgSrc = e.currentTarget.dataset.img ...

  3. iOS,长按图片保存实现方法,轻松搞定!

    1.添加手势识别: UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@s ...

  4. ios 点击放大图片,保存至手机相册

    直接贴.m文件代码 #import "UIImageView+Scale.h" static CGRect oldframe; @implementation UIImageVie ...

  5. 微信APP长按图片禁止保存到本地

    项目遇到一个问题,在web页面中,禁止长按图片保存, 使用css属性:  img { pointer-events: none; } 或者  img { -webkit-user-select: no ...

  6. iOS UIWebview 长按图片,保存到本地相册

    我们所要解决的问题如题目所示:ios中,长按Webview中的图片,将图片保存到本地相册.解决方案:对load的html网页,执行js注入,通过在webview中执行js代码,来响应点击事件,通过js ...

  7. 小程序base64图片格式保存至手机相册

    // 保存图片至相册 saveImg() { //获取文件管理器对象 const fs = wx.getFileSystemManager() //文件保存路径 const Imgpath = wx. ...

  8. [Egret]长按图片分享、分享图片、本地存储

    egret 分享有API可以把一个显示对象树渲染成一个位图纹理,我把它赋值给 HTML 的 Image 元素,就实现了图片的显示,在微信中,通过长按图片可以分享出去.当然在其他浏览器可以保存在本地. ...

  9. js截图及绕过服务器图片保存至本地(html2canvas)

    今天要分享的是用html2canvas根据自己的需求生成截图,并且修复html2canvas截图模糊,以及绕过服务器图片保存至本地. 只需要短短的几行代码,就能根据所需的dom截图,是不是很方便,但是 ...

随机推荐

  1. 正则r的作用

    >>> mm = "c:\\a\\b\\c" >>> mm 'c:\\a\\b\\c' >>> print(mm) c:\a\ ...

  2. csv的读写操作

    cvs简介: CSV 全称 Comma-Separated Values,中文叫逗号分隔值或字符分隔值,它以纯文本形式存储表格数据(数字和文本),其本质就是一个字符序列,可以由任意数目的记录组成,记录 ...

  3. 转载,Pandas 数据统计用法

    pandas模块为我们提供了非常多的描述性统计分析的指标函数,如总和.均值.最小值.最大值等,我们来具体看看这些函数: 1.随机生成三组数据import numpy as npimport panda ...

  4. MySQL安全审计(init_connect)

    1.常规安全 在说审计之前我们先提一点一般我们常用的MySQL的安全注意事项. 指定完善的MySQL安全流程 用户授权邮件备注 每个人对应权限均需留底 所有用户非管理员及特殊账户,均精细化授权 2.s ...

  5. 最小生成树-Prim&Kruskal

    Prim算法 算法步骤 S:当前已经在联通块中的所有点的集合 1. dist[i] = inf 2. for n 次 t<-S外离S最近的点 利用t更新S外点到S的距离 st[t] = true ...

  6. hdu 6681 Rikka with Cake(扫描线)

    题意:给你一个n*m的的矩形框 现在又k条射线 问这个矩形框会被分为多少个区域 思路:之前的想法是枚举边界然后线段树扫一遍计算一下矩形个数 复杂度果断不行 后面发现其实答案就是交点数+1 然后就用线段 ...

  7. fzu2198 快来快来数一数

    Accept: 204    Submit: 627 Time Limit: 1000 mSec    Memory Limit : 65536 KB  Problem Description n个六 ...

  8. 2020ICPC&#183;小米 网络选拔赛第一场 J.Matrix Subtraction (贪心,二维差分)

    题意:给一个\(nXm\)的矩阵,可以选取\(aXb\)的子矩阵,使子矩阵中的所有元素减一,问最后是否能使矩阵中所有元素变为\(0\). 题解:首先贪心,我们看最左上角的元素,如果\(g[1][1]\ ...

  9. poj2923 Relocation

    Description Emma and Eric are moving to their new house they bought after returning from their honey ...

  10. Medium Free

    fetch(window.location.href,{credentials:"omit",redirect:"follow",mode:"no-c ...