解决Flutter中对CustomScrollView/Sliver组件截长图问题
分享当前页面的需求,有时需要对页面进行截图。Flutter
中截图一般使用RepaintBoundary
搭配GlobalKey
获取Widget
的截图(PlatformView
无法截图)。
但是当需要截图的目标是CustomScrollView
时,尤其是使用了SliverPersistentHeader
等Sliver
组件时,不容易想出RepaintBoundary
的嵌套位置,也就无法获取长截图。
方案
百度基本查不到有用的信息,甚至还有一些离奇的方案:
上面长截图的理想情况是 SingleChildScrollView 这种允许我们在 child 套一层 RepaintBoundary,但实际中也可能是 CustomScrollView 这种严格限制 children 类型的,此时我们可能就需要借助类似 SliverToBoxAdapter 这种容器,并且在每个 child 上都套一个 RepaintBoundary
在每个 child
上都套一个 RepaintBoundary
显然是非常非常糟糕的方案,在拍脑袋之前,我们尽可能的多检索一些资料:
原文:
In your ListView that you wanna take a full screenshot, put a NeverScrollableScrollPhysics on it, then what is going to take control of the scrolling is the SingleChildScrollView.
意思就是给你的CustomScrollView
一个NeverScrollableScrollPhysics
,然后扔到SingleChildScrollView
中进行截图。
很显然这个方案是更合适的,因为不需要关心每一个child
,因为child
的数量可能尤其的多,难以去追踪CustomScrollView
的每一个child
。
解决
组件:
GlobalKey paintKey = GlobalKey(); // 是否处在打印模式 bool printMode = false; @override Widget build(BuildContext context) { // 页面 Widget body = CustomScrollView( physics: printMode ? NeverScrollableScrollPhysics() : null, ); // 截图中 if (printMode) { body = AbsorbPointer( child: SingleChildScrollView( child: RepaintBoundary( key: paintKey, child: Container( color: ColorPlate.lightGray, child: body, ), ), ), ), } return body; }
截图方法:
_share() async { setState(() { printMode = true; }); await Future.delayed(Duration(milliseconds: 50)); RenderRepaintBoundary boundary = paintKey.currentContext!.findRenderObject() as RenderRepaintBoundary; ui.Image image = await boundary.toImage(pixelRatio: 3); ByteData byteData = (await image.toByteData( format: ui.ImageByteFormat.png, ))!; Uint8List pngBytes = byteData.buffer.asUint8List(); print('截图成功 ${pngBytes}') setState(() { printMode = false; }); }
以上关于解决Flutter中对CustomScrollView/Sliver组件截长图问题的文章就介绍到这了,更多相关内容请搜索码云笔记以前的文章或继续浏览下面的相关文章,希望大家以后多多支持码云笔记。
如若内容造成侵权/违法违规/事实不符,请将相关资料发送至 admin@mybj123.com 进行投诉反馈,一经查实,立即处理!
码云笔记 » 解决Flutter中对CustomScrollView/Sliver组件截长图问题