Flutter中对webview截图


最近碰到个需求,在flutter中对webview进行截图,一想这还不简单,直接用Stack在webview上面放个按钮不就行了,然鹅实际试了一下发现,

  1. 官方的webview的层级太高,在Stack里面加的组件全部渲染到下面去了,根据看不见。
  2. 使用RepaintBoundary对webview截图的时候发现,截取的图是空白的。

现在讲下对两种组件进行截图的方式:

一、对普通的widget进行截图

对普通的组件进行截图的话,使用RepaintBoundary包裹需要截图的组件就行。

GlobalKey rootWidgetKey = GlobalKey();
Uint8List bytes;

body: RepaintBoundary(
        key: rootWidgetKey,
        child: Container(
        child: Stack(
          children: [
              Container(
                width: ScreenUtil().setWidth(375),
                height: ScreenUtil().setHeight(857),
                color: Colours.blue_2,
                child: Text('截图测试'),
              ),
            Positioned(
                bottom: 0,
                left: 0,
                child: Column(
                  children: [
                    GestureDetector(
                      onTap: () {
                        _capturePng();
                      },
                      child: bytes == null ? Container(
                        color: Colours.orange,
                        child: Text('ddddd'),
                      ) : Container(
                          width: ScreenUtil().setWidth(375),
                          height: ScreenUtil().setHeight(375),
                          decoration: BoxDecoration(
                            color: Colours.red,
                            border: Border.all(width:ScreenUtil().setWidth(1), color: Colours.orange)
                          ),
                          child: Image.memory(bytes, width: ScreenUtil().setWidth(375),
                            height: ScreenUtil().setHeight(375),)),
                    ),
                  ],
                ))
          ],
        ),
      ), ),

//将截图转为Uint8List 并展示
 _capturePng() async {
    try {
      RenderRepaintBoundary boundary =
      rootWidgetKey.currentContext.findRenderObject();
      double dpr = window.devicePixelRatio; // 获取当前设备的像素比
      var image = await boundary.toImage(pixelRatio: dpr);
      ByteData byteData = await image.toByteData(format: ImageByteFormat.png);
      Uint8List pngBytes = byteData.buffer.asUint8List();
      bytes = pngBytes;
     
      images.add(pngBytes);
      setState(() {
    
      });
      return pngBytes;
    } catch (e) {
      print(e);
    }
    return null;
  }
二、对webview截图

官方的webivew的层级太高会无法展示按钮,且通过RepaintBoundary截图是空白的。
需要使用flutter_inappwebview插件,这个插件有自带的截图功能

InAppWebViewController _webViewController;
Uint8List bytes;

body: RepaintBoundary(
        key: rootWidgetKey,
        // controller: screenshotController,
        child: Container(
        child: Stack(
          children: [
              Container(
                width: ScreenUtil().setWidth(375),
                height: ScreenUtil().setHeight(857),
                color: Colours.blue_2,
                child: InAppWebView(
                  initialUrlRequest: URLRequest(
                      url: Uri.parse(
                          '网址')),
                  onWebViewCreated: (InAppWebViewController controller) {
                    _webViewController = controller;
                  },
                  onLoadStart: (InAppWebViewController controller, Uri url) {},
                  onLoadStop:(InAppWebViewController controller, Uri url) async {
},
                ),
              ),

            Positioned(
                bottom: 0,
                left: 0,
                child: Column(
                  children: [
                    GestureDetector(
                      onTap: () {
                        _capturePng();
                      },
                      child: bytes == null ? Container(
                        color: Colours.orange,
                        child: Text('ddddd'),
                      ) : Container(
                          width: ScreenUtil().setWidth(375),
                          height: ScreenUtil().setHeight(375),
                          decoration: BoxDecoration(
                            color: Colours.red,
                            border: Border.all(width:ScreenUtil().setWidth(1), color: Colours.orange)
                          ),
                          child: Image.memory(bytes, width: ScreenUtil().setWidth(375),
                            height: ScreenUtil().setHeight(375),)),
                    ),
                  ],
                ))
          ],
        ),
      ), ),

_capturePng() async {
//使用按钮的方式
    bytes = await _webViewController.takeScreenshot();
    setState(() {});
}

如果想在webview加载完时就自动截图的话 则需要在InAppWebView的onLoadStop中操作

onLoadStop:(InAppWebViewController controller, Uri url) async {
  bytes = await controller.takeScreenshot();
},