captureOffscreenWidget method
Capturar screenshot de un widget específico fuera del árbol de widgets
Implementation
Future<String?> captureOffscreenWidget(
Widget widget, {
Size? size,
double? pixelRatio,
}) async {
try {
final Size logicalSize = size ?? const Size(400, 300);
final double actualPixelRatio = pixelRatio ??
ui.PlatformDispatcher.instance.views.first.devicePixelRatio;
// Crear renderización offscreen
final repaintBoundary = RenderRepaintBoundary();
final renderView = RenderView(
view: ui.PlatformDispatcher.instance.views.first,
child: RenderPositionedBox(
alignment: Alignment.center,
child: repaintBoundary,
),
configuration: ViewConfiguration(
logicalConstraints: BoxConstraints.tight(logicalSize),
devicePixelRatio: 1.0,
),
);
final pipelineOwner = PipelineOwner();
final buildOwner = BuildOwner(focusManager: FocusManager());
pipelineOwner.rootNode = renderView;
renderView.prepareInitialFrame();
// Adjuntar widget al árbol de renderizado
final rootElement = RenderObjectToWidgetAdapter<RenderBox>(
container: repaintBoundary,
child: Directionality(
textDirection: TextDirection.ltr,
child: MediaQuery(
data: const MediaQueryData(),
child: Material(
child: widget,
),
),
),
).attachToRenderTree(buildOwner);
buildOwner.buildScope(rootElement);
buildOwner
..buildScope(rootElement)
..finalizeTree();
// Renderizar
pipelineOwner
..flushLayout()
..flushCompositingBits()
..flushPaint();
// Capturar imagen
final ui.Image image =
await repaintBoundary.toImage(pixelRatio: actualPixelRatio);
final ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) return null;
final Uint8List pngBytes = byteData.buffer.asUint8List();
final String base64Image = base64Encode(pngBytes);
ObslyLogger.debug(
'Offscreen widget screenshot captured (${pngBytes.length} bytes)');
return 'data:image/png;base64,$base64Image';
} catch (e) {
ObslyLogger.error('Error capturing offscreen widget screenshot: $e');
return null;
}
}