在pubspec.yaml文件添加插件

  • image_gallery_saver安装1.5.0版本就好了,我之前安装的1.6.6会报错
  # 权限控制插件permission_handler: 5.0.1permission_handler_platform_interface: ^2.0.1# 文件保存插件image_gallery_saver: 1.5.0
  • 记得安装一下
flutter pub get

android和ios配置

ios 修改文件

  • 在ios/Runner/Info.plist添加以下代码
 <key>NSPhotoLibraryUsageDescription</key><string></string><key>NSPhotoLibraryAddUsageDescription</key><string>请允许APP保存图片到相册</string>

android 修改文件

  • 在android/app/src/main/AndroidManifest.xml添加以下代码
    <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"/>

将需要生成图片的组件用RepaintBoundary包裹

GlobalKey globalKey = GlobalKey();
RepaintBoundary(key: globalKey,child:Text('我要生成图片'),)

保存图片到相册

在点击事件里调用这个方法就可以了

 /// 保存图片static Future<void> saveImage(GlobalKey globalKey) async {RenderRepaintBoundary boundary =globalKey.currentContext.findRenderObject();var image = await boundary.toImage(pixelRatio: 6.0);ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);Uint8List pngBytes = byteData.buffer.asUint8List();// final result = await ImageGallerySaver.saveImage(pngBytes,//     quality: 60, name: "hello");// if (result) {//   print('ok');//   // toast("保存成功", wring: false);// } else {//   print('error');// }if (Platform.isIOS) {var status = await Permission.photos.status;if (status.isUndetermined) {Map<Permission, PermissionStatus> statuses = await [Permission.photos,].request();saveImage(globalKey);}if (status.isGranted) {final result = await ImageGallerySaver.saveImage(pngBytes,quality: 60, name: "hello");if (result) {print('ok');// toast("保存成功", wring: false);} else {print('error');// toast("保存失败");}}if (status.isDenied) {print("IOS拒绝");}} else if (Platform.isAndroid) {var status = await Permission.storage.status;if (status.isUndetermined) {Map<Permission, PermissionStatus> statuses = await [Permission.storage,].request();saveImage(globalKey);}if (status.isGranted) {print("Android已授权");final result = await ImageGallerySaver.saveImage(pngBytes, quality: 60);if (result != null) {print('ok');// toast("保存成功", wring: false);} else {print('error');// toast("保存失败");}}if (status.isDenied) {print("Android拒绝");}}}

完整demo代码

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:interviewer_app/common/component_index.dart';
// 一定要引入这三个插件
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart';
import 'package:permission_handler/permission_handler.dart';import 'package:flutter/services.dart';
import 'dart:ui' as ui;
import 'dart:typed_data';
import 'dart:io';class ShareJob extends StatefulWidget {const ShareJob({Key key, this.searchKey}) : super(key: key);final String searchKey;@overrideState<StatefulWidget> createState() {return new _ShareJobState();}
}class _ShareJobState extends State<ShareJob> {// globalKey 在这里设置GlobalKey globalKey = GlobalKey();Uint8List newPngBytes;Widget shareImage() {returnRepaintBoundary(key: globalKey,child:Container(child:// 图片Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [Container(alignment: Alignment.center,decoration: BoxDecoration(color: Color(0xFF5B9AFF),boxShadow:[BoxShadow(color: Color(0x1A000000),offset: Offset(0, 5.0),blurRadius: 24.0),]),width: MediaQuery.of(context).size.width * 0.6,child:Column(children: [Gaps.vGap25,Text('热招职位', style: TextStyle(fontSize: 22, color: Colors.white, fontWeight: FontWeight.w300),),Gaps.vGap25,Container(margin: EdgeInsets.only(bottom: 22,left: 15,right: 15),// padding: EdgeInsets.only(bottom: 22,left: 15,right: 15),alignment: Alignment.center,decoration: BoxDecoration(color: Colors.white,borderRadius: BorderRadius.circular(10.0),boxShadow:[BoxShadow(color: Color(0x1A000000),offset: Offset(0, 5.0),blurRadius: 24.0),]),// padding: EdgeInsets.all(10),// margin: EdgeInsets.only(bottom: 6),// width: MediaQuery.of(context).size.width * 0.6,// height: 305,child: Column(children: [Gaps.vGap25,Gaps.vGap10,Text('测试工程师', style: TextStyle(fontSize: 15, color: Color(0xFF313753), fontWeight: FontWeight.w500),),Gaps.vGap10,Text('15k-20K | 上海', style: TextStyle(fontSize: 15, color: Color(0xFFF4A25A), fontWeight: FontWeight.w500),),Gaps.vGap10,Text('公司名', style: TextStyle(fontSize: 10, color: Color(0xFF313753), fontWeight: FontWeight.w400),),Gaps.vGap15,Image.asset(Utils.getImgPath('checked'),width: 115.0),Gaps.vGap25,Text('长按查看职位详情', style: TextStyle(fontSize: 9, color: Color(0xFF313753), fontWeight: FontWeight.w400),),Gaps.vGap25,],),),],),),],),));}/// 保存图片static Future<void> saveImage(GlobalKey globalKey) async {RenderRepaintBoundary boundary =globalKey.currentContext.findRenderObject();var image = await boundary.toImage(pixelRatio: 6.0);ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);Uint8List pngBytes = byteData.buffer.asUint8List();// final result = await ImageGallerySaver.saveImage(pngBytes,//     quality: 60, name: "hello");// if (result) {//   print('ok');//   // toast("保存成功", wring: false);// } else {//   print('error');// }if (Platform.isIOS) {var status = await Permission.photos.status;if (status.isUndetermined) {Map<Permission, PermissionStatus> statuses = await [Permission.photos,].request();saveImage(globalKey);}if (status.isGranted) {final result = await ImageGallerySaver.saveImage(pngBytes,quality: 60, name: "hello");if (result) {print('ok');// toast("保存成功", wring: false);} else {print('error');// toast("保存失败");}}if (status.isDenied) {print("IOS拒绝");}} else if (Platform.isAndroid) {var status = await Permission.storage.status;if (status.isUndetermined) {Map<Permission, PermissionStatus> statuses = await [Permission.storage,].request();saveImage(globalKey);}if (status.isGranted) {print("Android已授权");final result = await ImageGallerySaver.saveImage(pngBytes, quality: 60);if (result != null) {print('ok');// toast("保存成功", wring: false);} else {print('error');// toast("保存失败");}}if (status.isDenied) {print("Android拒绝");}}}@overrideWidget build(BuildContext context) {return new Scaffold(appBar: AppBar(title: Text('分享职位'), titleSpacing: 0, centerTitle: true),body: SingleChildScrollView(child: Container(child: Column(children: [Gaps.vGap25,Row(children: [// http://images.shejidaren.com/wp-content/uploads/2020/03/36365-4.png// IconButton(//   iconSize: 22,//   icon: const Icon(Icons.close),//   onPressed: (){//   },// )Gaps.hGap30,Gaps.hGap10,Gaps.hGap10,Column(children: [Container(decoration: new BoxDecoration(color: Cor.roundbg_1,borderRadius: BorderRadius.circular(100),),padding: EdgeInsets.all(10),margin: EdgeInsets.only(bottom: 6),width: 60,height: 60,child: Image.network('http://images.shejidaren.com/wp-content/uploads/2020/03/36365-4.png'),),Text('微信好友',textAlign: TextAlign.center,style: TextStyle(color: Cor.black_1, fontSize: 14),)],),Gaps.hGap30,Gaps.hGap10,Gaps.hGap10,Column(children: [Container(decoration: new BoxDecoration(color: Cor.roundbg_1,borderRadius: BorderRadius.circular(100),),padding: EdgeInsets.all(10),margin: EdgeInsets.only(bottom: 6),width: 60,height: 60,child: Image.network('https://www.sj520.cn/sc/ima/weixin_sj520_11.jpg'),),Text('朋友圈',textAlign: TextAlign.center,style: TextStyle(color: Cor.black_1, fontSize: 14),)],),],),Gaps.vGap20,// 灰色横线Container(decoration: new BoxDecoration(color: Cor.roundbg_1),width: double.infinity,height: 10,),Gaps.vGap15,Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [Text('已生成朋友圈图片',textAlign: TextAlign.center,style: TextStyle(color: Cor.black_1.withOpacity(0.65), fontSize: 14),),],),Gaps.vGap15,shareImage(),Gaps.vGap15,Gaps.vGap10,Row(mainAxisAlignment: MainAxisAlignment.spaceAround,children: [RaisedButton(color: Cor.blue_1,highlightColor: Colors.blue[100],colorBrightness: Brightness.dark,splashColor: Cor.blue_2,padding: EdgeInsets.only(left: 34,right: 34),child: Text("保存至相册",style: TextStyle(color: Colors.white, fontSize: 14),),shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),onPressed: () async {print('------');print(globalKey.currentContext);// createImageFromRepaintBoundary(globalKey);// final g = createImageFromWidget(saveImage());// print(g);saveImage(globalKey);},),],),Gaps.vGap25,Gaps.vGap25,]),),),);}
}

效果图

保存成功后可以在模拟器相册看到

公众号

欢迎大家关注我的公众号: 石马上coding,一起成长

flutter 生成图片保存到手机相册相关推荐

  1. 微信小程序之通过Canvas生成图片保存到手机相册

    需求描述: 电商项目中有很多需要分享邀请的海报页面,需要带上自己的小程序码,并且保存在本地,然后分享到朋友圈. 解决方法: 将海报通过wx.createCanvasContext绘制到画布canvas ...

  2. 微信小程序第四篇:生成图片并保存到手机相册

    系列文章传送门: 微信小程序第一篇:自定义组件详解 微信小程序第二篇:七种主流通信方法详解 微信小程序第三篇:获取页面节点信息 目录 一.封装分享组件 二.定义用户授权方法 三.调用流程 首先我们看一 ...

  3. uniapp canvas 图片加上文字合成一张新图并保存到手机相册

    uniapp canvas 图片加上文字合成一张新图并保存到手机相册 背景图上是奖章徽章,中间加上自定义文本,我这个图是因为背景图上原来就有字,随便找的,所以跟我写的文字层叠了 具体实现代码 < ...

  4. 前端Vue H5生成带二维码的分享海报,实现长按保存到手机相册

    前端Vue H5生成带二维码的分享海报,实现长按保存到手机相册 前言:关于H5分享海报的需求,经常会遇到,通常就是一个分享的二维码+分享文案,生成一张图片,供用户在手机上长按保存到手机,然后就可以将保 ...

  5. 微信动态表情保存到手机相册

    微信表情包不能下载到手机相册,一直是许多用户头疼的一个问题,现在关注了这个小工具,只需简单一步,就能立即把想要的表情保存到本地手机相册,轻轻松松3秒搞定. 01 关注公众号:表情保存神器 02 把需要 ...

  6. uni-app app端用highcharts绘制图表,并生成海报保存到手机相册

    uni-app 打包app后 highcharts图表绘制不成功,不支持该方法,所以就考虑在app中嵌入webview h5页面,实现图表的绘制. 首先引用安装highcharts,封装成一个组件 n ...

  7. 直播app源代码,手机屏幕截取并保存到手机相册

    直播app源代码,实现手机屏幕截取并保存到手机相册功能的代码 public void convertViewToBitmap(View a) {//用时间来命名文件名SimpleDateFormat ...

  8. 小程序canvas生成海报保存至手机相册

    小程序canvas画图保存至手机相册 (1)可直接展示生成的海报 .因手机分辨率不同可能导致生成的海报会有细微差别,这里隐藏canvas海报,页面正常设置海报样式保存时保存隐藏的canvas海报 (2 ...

  9. 微信小程序使用canvas画图并保存到手机相册踩坑总结

    接到个项目做微信小程序的,需要将手机中的页面保存到手机相册中,效果图如下 首先想到的就是利用canvas画图然后在保存到相册,看起来很简单网上也有很多例子,但都不完整,很多网友分享的都在半吊子工程,只 ...

  10. 将微信里的表情保存到手机相册

    大家都遇到过微信里面的表情包保存不到手机相册的问题吧,今天就来给大家分享个黑科技,能把微信表情保存到手机相册,然后可以在QQ里面,电脑里面使用. 目前是最新,最简单,最有效的方法.按照下面步骤来. 1 ...

最新文章

  1. 【camera】2.相机成像原理和数学模型
  2. Visual Studio 2005 Professional Released
  3. 常见的权限访问控制模型
  4. 如何使用 backupninja 来备份 Debian 系统
  5. Atitit mysql 数据类型 5.7.9 目录 1.1. 数值类型 1 2. 字符串 2 3. 时间日期 2 4. 地理位置 2 5. 几何数据的存储,生成,分析,优化。 空间数据类型(存储)
  6. android 日历 定制,Android自定义View(CustomCalendar-定制日历控件)
  7. 语言缩写c-a,各国语言缩写及语言代码查询
  8. office2016显示已经激活,但每次打开都跳出激活页面
  9. 转型只争朝夕!又一火电企业成立新能源公司
  10. 【TWS使用系列1】如何从TWS的自选列表中添加/删除自选股?
  11. TensorFlow Serving架构分析
  12. 苹果计算机开机进入安全模式,苹果电脑开机步骤
  13. 35岁是个坎,为啥到岁数就不想要你了
  14. uniapp的分享到朋友圈和朋友(APP)
  15. 跟未名学Office - PPT操作:高效
  16. 用python实现自动化办公------定时发送微信消息
  17. 安卓电池校正_笔记本电池损耗55%后一波三折的挽救经历
  18. 【arduino从入门到放肆】⑥Arduino 小台灯
  19. SMETA验厂辅导,Sedex和BSCI的区别在哪及Sedex验厂审核的流程
  20. 【学习笔记】Spring-IOC-DI-AOP 学习笔记

热门文章

  1. java环境安装1359错误_iserver java api接口频发错误
  2. CENTOS7 安装mantis
  3. Unity3D基础3:贴图与材质球
  4. 单U盘 clonezilla 克隆ubuntu16.04系统
  5. Elasticsearch 7.7.0 高阶篇-聚合技术
  6. 如何培养孩子一年读100本书
  7. wordpress企业主题
  8. A-Z,所有汽车品牌完整json格式
  9. 我叫MT online 公会BOSS百分比、难度、BOSS技能及站位
  10. 微信分享代码,朋友圈分享代码