这是【Flutter 问题系列第 22 篇】,如果觉得有用的话,欢迎关注专栏。

关于在 Flutter 中如何截取屏幕,以及如何将截图保存到相册的文章少之又少,即使有,也是错误一大片,有的甚至运行后都报错,就这都直接发出来了,真是可恶啊!

所以我整理了这篇博客,实现了两个功能

  • 如何截取整个屏幕或屏幕中的某一部分,并显示到页面中
  • 如何将截取的图片,保存到相册中

这两个功能都已亲测并无问题,源码会全部奉上,如果有用,希望可以给个三连,接下来是博客正文。

文章目录

  • 一:如何截取屏幕,并显示到页面中
    • 1:RepaintBoundary 组件介绍
    • 2:如何截图
    • 3:如何在页面中显示截图
  • 二:如何将截取到的图片,保存到相册中
    • 1:配置权限、引用插件
    • 2:存储图片到相册

一:如何截取屏幕,并显示到页面中

依照国际惯例,先上效果图(没有先看到效果图,估计你们都会走吧~)

由效果图可以看出来,截取到的每一帧都是不同的图片,功能实现了,接下来就是如何实现功能的代码了。

1:RepaintBoundary 组件介绍

我们知道在 Flutter 中万物皆组件,所以接下来要说的截图其实也是一个组件,与其说是截取屏幕,不如说是截取组件。

而这个组件的名称就是 RepaintBoundary ,源码如下所示

 RepaintBoundary({ Key key, Widget child })

使用起来也很简单,直接套在你想要截的组件上面就行了,如果你要截取的是整个页面,套在 Scaffold 外面即可。

因为 RepaintBoundary 继承自 SingleChildRenderObjectWidget 而我们又需要获取到被截取组件的状态,所以第一个参数 Key 的类型应为 GlobalKey,如下所示

GlobalKey _repaintKey = GlobalKey(); // 可以获取到被截图组件状态的 GlobalKey

而第二个参数就是你需要截取的组件,如下代码所示

RepaintBoundary(key: _repaintKey,child: Image.asset("assets/girl.gif", width: 200, height: 200, fit: BoxFit.cover),
)

2:如何截图

接下来要说的是最核心的部分了,就是如何获取到截取图片的数据。

这里我直接把代码复制到下方了,关键代码都有解释,相信大家一看就懂了。

 /// 获取截取图片的数据Future<Uint8List> _getImageData() async {BuildContext buildContext = _repaintKey.currentContext;if (buildContext != null) {RenderRepaintBoundary boundary = buildContext.findRenderObject();// 第一次执行时,boundary.debugNeedsPaint 为 true,此时无法截图(如果为true时直接截图会报错)if (boundary.debugNeedsPaint) {// 延时一定时间后,boundary.debugNeedsPaint 会变为 false,然后可以正常执行截图的功能await Future.delayed(Duration(milliseconds: 20));// 重新调用方法return _getImageData();}// 获取当前设备的像素比double dpr = ui.window.devicePixelRatio;// pixelRatio 代表截屏之后的模糊程度,因为不同设备的像素比不同// 定义一个固定数值显然不是最佳方案,所以以当前设备的像素为目标值ui.Image image = await boundary.toImage(pixelRatio: dpr);ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);Uint8List imageBytes = byteData.buffer.asUint8List();// 返回图片的数据return imageBytes;}}

这里将图片数据以 Uint8List 的格式返回,方便后面显示图片。

3:如何在页面中显示截图

我们可以通过 Image.memory(); 方法从内存中加载图片,而该方法需要传入图片的数据,数据类型是 Uint8List ,这也是为什么要把图片数据以 Uint8List 类型返回了。

如果要显示的截图有多张,则定义一个列表

List<Uint8List> _images = []; // 存放所有截图的列表

然后当点击底部按钮时,执行如下函数

/// 执行截图并显示到页面中
void _doScreenShots() async {Uint8List data = await _getImageData();_images.add(data);setState(() {});
}

最后就是遍历这个列表,把图片显示出来就行了,如下代码所示

GridView.builder(gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3,),itemCount: _images.length,itemBuilder: (BuildContext context, int index) {if (_images.isEmpty) {return Container();}return Image.memory(_images[index], fit: BoxFit.cover);},
)

至此,如何截取屏幕,并显示到页面中便介绍完毕了,一定要注意的是,当 _getImageData() 方法中的 boundary.debugNeedsPaint 为 true 时,一定不要去截图,一定不要去截图,一定不要去截图,否则会报

‘!debugNeedsPaint’:is not true 的错误,切记!!!

二:如何将截取到的图片,保存到相册中

如何截图已经说过了,如何将截图保存到相册中呢?

1:配置权限、引用插件

保存到相册的话就要涉及到存储文件的权限,以及如何把图片保存到相册的问题了。

这里引用两个插件

  • 权限控制插件 permission_handler
  • 图片存储到相册插件 image_gallery_saver

然后在 pubspec.yaml 文件中引入这两个插件,如下所示

dependencies:permission_handler: ^8.1.1 # 权限控制插件 by Allen Suimage_gallery_saver: ^1.6.9 # 图片存储到相册插件 by Allen Su

安卓系统,需要在 android/app/src/main/AndroidManifest.xml 文件中添加如下代码

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!--写入外部存储权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <!--读取外部存储权限-->

苹果系统,需要在 ios/Runner/Info.plist 文件中添加如下代码

<key>NSPhotoLibraryAddUsageDescription</key>
<string>请允许APP保存图片到相册</string>

(因博主是从事安卓开发的,关于 ios 这里是翻阅的资料,并没有证实,应该没有什么问题)

2:存储图片到相册

权限问题解决了,接下来就是如何把截图存储到本地相册了,很简单,其实一行代码就可以了,下面的代码包含获取存储权限和存储图片到相册,如下所示

/// 执行存储图片到本地相册
void _doSaveImage() async {// 如果用户已授权存储权限if (await Permission.storage.request().isGranted) {Uint8List data = await _getImageData();await ImageGallerySaver.saveImage(data);} else {// 没有存储权限时,弹出没有存储权限的弹窗}
}

当点击按钮时,是获取权限,如下图所示

点击允许后,图片会自动保存到相册,如下图所示

可以看到,这是已经保存到相册后的视图了,至此,关于在 Flutter 中如何截取屏幕并显示到页面中,以及如何将截图保存到相册便介绍完毕了,按照我写的一步一步来,应该不会有什么问题。

你的问题得到解决了吗?欢迎在评论区留言。

赠人玫瑰,手有余香,如果觉得文章不错,希望可以给个一键三连,感谢。


结束语

Google 的 Flutter 越来越火,截止 2021年6月3日 GitHub 标星已达 123K,Flutter 毅然是一种趋势,所以作为前端开发者,没有理由不趁早去学习。

无论你是 Flutter 新手还是已经入门了,不妨先点个关注,后续我会将 Flutter 中的常用组件(含有源码分析、组件的用法及注意事项)以及可能遇到的问题写到 CSDN 博客中,希望自己学习的同时,也可以帮助更多的人。

【Flutter 问题系列第 22 篇】在 Flutter 中如何截取屏幕并显示到页面中,以及如何将截图保存到相册相关推荐

  1. 【Flutter 问题系列第 71 篇】Flutter 中 Uint8List 和 Image 之间的相互转换

    这是[Flutter 问题系列第 71 篇],如果觉得有用的话,欢迎关注专栏. Flutter 版本:2.5.0,Dart 版本:2.14 因为最近一直在处理照相机.裁剪图片和 OCR 图片识别的功能 ...

  2. 【Flutter 问题系列第 5 篇】Flutter 去除 ListView 组件中的蓝色回弹效果

    这是[Flutter 问题系列第 5 篇],如果觉得有用的话,欢迎关注专栏. ListView 组件默认的滑动效果如下 可以看到,在顶部向下拖动或者到底部向上拖动时,会有一个蓝色的回弹效果. 这是因为 ...

  3. 【Flutter 问题系列第 15 篇】如何给 Flutter 中的图片设置透明度

    这是[Flutter 问题系列第 15 篇],如果觉得有用的话,欢迎关注专栏. 在 Flutter 中,如果背景色是颜色的话,我们知道可以直接通过 Color.fromRGBO(r, g, b, op ...

  4. 【Flutter 问题系列第 41 篇】Cannot provide both a color and a decoration,To provide both, use “decoration“

    这是[Flutter 问题系列第 41 篇],如果觉得有用的话,欢迎关注专栏. 这个错误相信每一个刚接触 Flutter 的都会碰到,不是什么大问题,只是一个注意事项而已. 一:报错信息 示例代码如下 ...

  5. 【Flutter 组件系列第 2 篇】CircularProgressIndicator (圆形进度条组件)

    这是[Flutter 组件系列第 2 篇],如果觉得有用的话,欢迎关注专栏. 文章目录 一:CircularProgressIndicator 的构造函数 二:基本用法 三:设置进度具体值 四:设置背 ...

  6. 【Flutter 问题系列第 40 篇】如何给 Container 四周设置圆角以及给某一角设置圆角

    这是[Flutter 问题系列第 40 篇],如果觉得有用的话,欢迎关注专栏. Container 组件有一个属性 BoxDecoration ,可以用来修改样式 1.给 Container 四周设置 ...

  7. 【Flutter 问题系列第 46 篇】如何修改 Flutter 项目的包名

    这是[Flutter 问题系列第 46 篇],如果觉得有用的话,欢迎关注专栏. 如果你开发过 Android 原生的项目,修改项目的包名只需要修改 android - app - build.grad ...

  8. 【Flutter 问题系列第 19 篇】安装 apk 包时提示 Install canceled by user 的问题如何解决

    这是[Flutter 问题系列第 19 篇],如果觉得有用的话,欢迎关注专栏. 一:问题描述 公司的测试机中我用的是小米的,用着一直没问题,这不五一想着用自己的 Redmi Note 9 Pro 跑一 ...

  9. 【Flutter 问题系列第 36 篇】The shrinker may have failed to optimize the Java bytecode

    这是[Flutter 问题系列第 36 篇],如果觉得有用的话,欢迎关注专栏. 这个问题今天也是第一次碰到,特此记录下,报错信息如下图所示 错误关键词是 The shrinker may have f ...

最新文章

  1. webpack配置模块的查找范围
  2. 关于DiscuzNT 1.0
  3. 关于同源策略的一些想法
  4. 12.引入依赖项目的时候,如果找不到jar
  5. 大数据开发笔记(四):Hive分区详解
  6. IM即时通讯源码系统安卓苹果IOS双端源码介绍
  7. android开发笔记之 国家/地区语言速查表
  8. 如何软件自动生成延时函数
  9. python 显示gif_使用tkinter显示动态gif
  10. 一个交警的吐血警告,所有开车和坐车的同胞都要看一看(转)
  11. Discuz!模板解析语法
  12. 李银河应该重读王小波《摆脱童稚状态》--尼伯龙根·蜗藤
  13. 计算机开机出现ROM,求助电脑开机问题
  14. c语言文件被认为是木马,为啥我用c语言写成的exe文件会被360当做木马?
  15. 报盘、还盘的英语短句(建议收藏)
  16. 概率校准calibration_curve,用Isotonic regression,得出calibration_curve的好坏,用交叉熵检验,和方差,及使用朴素贝叶斯方法
  17. 专题论坛:云计算安全论坛
  18. Orace登录及建库
  19. 我想是我该离开九又四分之三站台的时候了
  20. 输电线路杆塔、导线分割图像数据集(含分割标签,1242张图像),输电线路巡检图像数据

热门文章

  1. Git Basics - Viewing the Commit History
  2. android第二次点击应用,就报App isn't installed 解决方法
  3. back track 5 / BT5 默认用户名密码
  4. The Data Science of Gaming and Fantasy Sports 游戏与幻想体育的数据科学 Lynda课程中文字幕
  5. 重新排列句子 臃肿低效到简洁高效的算法
  6. linux安装的库文件,linux – 安装包库和头文件在哪里?
  7. 区块链+支付:区块链技术是什么?它如何在支付行业中使用?
  8. vue2.x版本+element-ui2.15+版本实现只能输入数字的ip输入框,功能样式借鉴windows,与父组件双向绑定
  9. mysql的blob字段存储中文,输出乱码
  10. c++多态(已知测试main函数,设计符合要求的Money类。 类Money: 数据成员:yuan,jiao,fen 成员函数:operator )