共计 1642 个字符,预计需要花费 5 分钟才能阅读完成。
问题
分享以后页面的需要,有时须要对页面进行截图。Flutter
中截图个别应用 RepaintBoundary
搭配 GlobalKey
获取 Widget
的截图(PlatformView
无奈截图)。
然而当须要截图的指标是 CustomScrollView
时,尤其是应用了 SliverPersistentHeader
等Sliver
组件时,不容易想出 RepaintBoundary
的嵌套地位,也就无奈获取长截图。
计划
百度根本查不到有用的信息,甚至还有一些离奇的计划:
下面长截图的现实状况是 SingleChildScrollView 这种容许咱们在 child 套一层 RepaintBoundary,但理论中也可能是 CustomScrollView 这种严格限度 children 类型的,此时咱们可能就须要借助相似 SliverToBoxAdapter 这种容器,并且在每个 child 上都套一个 RepaintBoundary
在每个 child
上都套一个 RepaintBoundary
显然是十分十分蹩脚的计划,在拍脑袋之前,咱们尽可能的多检索一些材料:
https://github.com/SachinGanesh/screenshot/issues/10#issuecomment-586302204
原文:
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;});
}