generateImageFromWidget static method

Future<ImageElement?> generateImageFromWidget(
  1. BuildContext context,
  2. Widget widget, [
  3. ImageElement? imageElement
])

Captures a widget-frame that is not build in a widget tree. Inspired by screenshot plugin

Implementation

static Future<ImageElement?> generateImageFromWidget(wid.BuildContext context, wid.Widget widget, [ImageElement? imageElement]) async {
  try {
    /// boundary widget by GlobalKey
    rend.RenderRepaintBoundary? boundary = rend.RenderRepaintBoundary();
    final flutterView = wid.View.of(context);
    final pixelRatio = flutterView.devicePixelRatio;
    wid.Size logicalSize = flutterView.physicalSize / pixelRatio;
    wid.Size imageSize = flutterView.physicalSize;

    assert(logicalSize.aspectRatio.toStringAsPrecision(5) == imageSize.aspectRatio.toStringAsPrecision(5));

    final rend.RenderView renderView = rend.RenderView(
      view: flutterView,
      child: rend.RenderPositionedBox(alignment: wid.Alignment.center, child: boundary),
      configuration: rend.ViewConfiguration(
        physicalConstraints: rend.BoxConstraints.tight(logicalSize) * pixelRatio,
        logicalConstraints: rend.BoxConstraints.tight(logicalSize),
        devicePixelRatio: pixelRatio,
      ),
    );

    final rend.PipelineOwner pipelineOwner = rend.PipelineOwner();
    final wid.BuildOwner buildOwner = wid.BuildOwner(focusManager: wid.FocusManager(), onBuildScheduled: () {});

    pipelineOwner.rootNode = renderView;
    renderView.prepareInitialFrame();

    final wid.RenderObjectToWidgetElement<rend.RenderBox> rootElement =
        wid.RenderObjectToWidgetAdapter<rend.RenderBox>(
          container: boundary,
          child: wid.Directionality(
          textDirection: wid.TextDirection.ltr,
          child: widget,
      )
    ).attachToRenderTree(
      buildOwner,
    );
    buildOwner.buildScope(
      rootElement,
    );
    buildOwner.finalizeTree();

    pipelineOwner.flushLayout();
    pipelineOwner.flushCompositingBits();
    pipelineOwner.flushPaint();

    /// convert boundary to image
    final image = await boundary.toImageSync(pixelRatio: pixelRatio);
    final data = (await image.toByteData(format: ui.ImageByteFormat.rawRgba))?.buffer.asUint8List();
    if(data == null){
      return null;
    }
    else if(imageElement != null){
      imageElement.width = image.width;
      imageElement.height = image.height;
      if(imageElement.data == null){
        imageElement.data = Uint8Array.fromList(data);
      }
      else{
        (imageElement.data as Uint8Array).set(data);
      }
      return imageElement;
    }
    return ImageElement(
      width: image.width,
      height: image.height,
      data: Uint8Array.fromList(data)
    );
  } catch (e) {
    rethrow;
  }
}