最近碰到个需求,在flutter中对webview进行截图,一想这还不简单,直接用Stack在webview上面放个按钮不就行了,然鹅实际试了一下发现,
- 官方的webview的层级太高,在Stack里面加的组件全部渲染到下面去了,根本看不见。
- 使用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();
},