flutter开发实战-RepaintBoundary实现Widget截图功能
在开发中,遇到需要使用截图,像iOS可以截图UIView获取到UIImage,在flutter中可以使用RepaintBoundary实现截图功能
相机拍摄的图片:
RepaintBoundary截图后的图片
一、RepaintBoundary
RepaintBoundary是绘制边界。
如果CustomPaint有子节点,为了避免子节点不必要的重绘并提高性能,通常情况下都会将子节点包裹在RepaintBoundary组件中,这样会在绘制时就会创建一个新的绘制层(Layer),其子组件将在新的Layer上绘制,而父组件将在原来Layer上绘制,也就是说RepaintBoundary 子组件的绘制将独立于父组件的绘制,RepaintBoundary会隔离其子节点和CustomPaint本身的绘制边界。示例如下:
CustomPaint(
size: Size(300, 300), //指定画布大小
painter: MyPainter(),
child: RepaintBoundary(child:...)),
)
参考:https://book.flutterchina.club/chapter10/custom_paint.html#_10-4-1-custompaint
二、实现Widget截图
实现Widget截图,需要将Widget嵌套在RepaintBoundary里,需要用到Globalkey
示例如下
Container(
width: widget.width,
height: widget.height,
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: Colors.transparent,
),
child: RepaintBoundary(
key: _cameraViewGlobalKey,
child: Transform.scale(
scale: scale * aspectRatio,
child: AspectRatio(
aspectRatio: aspectRatio,
child: Center(
child: CameraPreview(
controller!,
),
),
),
),
),
);
实现截图功能
// 根据GlobalKey来截图Widget
static Future<Uint8List?> makeImageUInt8List(GlobalKey globalKey) async {
RenderRepaintBoundary boundary =
globalKey.currentContext?.findRenderObject() as RenderRepaintBoundary;
// 这个可以获取当前设备的像素比
var dpr = ui.window.devicePixelRatio;
ui.Image image = await boundary.toImage(pixelRatio: dpr);
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List? pngBytes = byteData?.buffer.asUint8List();
return pngBytes;
}
获得Uint8List,可以直接将其写入文件或者使用Image展示。
if (uInt8List != null) {
await File(imagePath).writeAsBytes(uInt8List);
}
三、小结
flutter开发实战-RepaintBoundary实现Widget截图功能,像iOS可以截图UIView获取到UIImage,在flutter中可以使用RepaintBoundary实现截图功能。