【Flutter 问题系列第 22 篇】在 Flutter 中如何截取屏幕并显示到页面中,以及如何将截图保存到相册 |
您所在的位置:网站首页 › 苹果电脑截图怎么保存到相册 › 【Flutter 问题系列第 22 篇】在 Flutter 中如何截取屏幕并显示到页面中,以及如何将截图保存到相册 |
这是【Flutter 问题系列第 22 篇】,如果觉得有用的话,欢迎关注专栏。 关于在 Flutter 中如何截取屏幕,以及如何将截图保存到相册的文章少之又少,即使有,也是错误一大片,有的甚至运行后都报错,就这都直接发出来了,真是可恶啊! 所以我整理了这篇博客,实现了两个功能 如何截取整个屏幕或屏幕中的某一部分,并显示到页面中如何将截取的图片,保存到相册中这两个功能都已亲测并无问题,源码会全部奉上,如果有用,希望可以给个三连,接下来是博客正文。 文章目录 一:如何截取屏幕,并显示到页面中1:RepaintBoundary 组件介绍2:如何截图3:如何在页面中显示截图 二:如何将截取到的图片,保存到相册中1:配置权限、引用插件2:存储图片到相册 一:如何截取屏幕,并显示到页面中依照国际惯例,先上效果图(没有先看到效果图,估计你们都会走吧~) ![]() 我们知道在 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 _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 _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 Su image_gallery_saver: ^1.6.9 # 图片存储到相册插件 by Allen Su安卓系统,需要在 android/app/src/main/AndroidManifest.xml 文件中添加如下代码 苹果系统,需要在 ios/Runner/Info.plist 文件中添加如下代码 NSPhotoLibraryAddUsageDescription 请允许APP保存图片到相册(因博主是从事安卓开发的,关于 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 博客中,希望自己学习的同时,也可以帮助更多的人。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |