1

问题

分享当前页面的需求,有时需要对页面进行截图。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;

@override
Widget build(BuildContext context) {
// 页面
Widget body = CustomScrollView(
    shrinkWrap: printMode, // 注意正常情况下不要滥用shrinkWrap属性。
    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;
    });
  }

马嘉伦
874 声望845 粉丝