问题

分享以后页面的需要,有时须要对页面进行截图。Flutter中截图个别应用RepaintBoundary搭配GlobalKey获取Widget的截图(PlatformView 无奈截图)。

然而当须要截图的指标是CustomScrollView时,尤其是应用了SliverPersistentHeaderSliver组件时,不容易想出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;@overrideWidget 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;    });  }