captureOffscreenWidget method

Future<String?> captureOffscreenWidget(
  1. Widget widget, {
  2. Size? size,
  3. double? pixelRatio,
})

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;
  }
}