addImageFromWidget method

Future<void> addImageFromWidget({
  1. required String id,
  2. required Widget widget,
  3. Size? logicalSize,
  4. Size? imageSize,
  5. TextDirection textDirection = TextDirection.ltr,
})

Create an image from a Widget and add it to the map with the given id.

This method is inspired by the widget_to_marker package.

Implementation

Future<void> addImageFromWidget({
  required String id,
  required Widget widget,
  Size? logicalSize,
  Size? imageSize,
  TextDirection textDirection = TextDirection.ltr,
}) async {
  final rb = RepaintBoundary(
    child: MediaQuery(
      data: const MediaQueryData(),
      child: Directionality(textDirection: textDirection, child: widget),
    ),
  );

  final view = PlatformDispatcher.instance.views.first;

  final repaintBoundary = RenderRepaintBoundary();
  logicalSize ??= view.physicalSize / view.devicePixelRatio;
  imageSize ??= view.physicalSize;

  final renderView = RenderView(
    view: view,
    child: RenderPositionedBox(child: repaintBoundary),
    configuration: ViewConfiguration(
      physicalConstraints:
          BoxConstraints.tight(logicalSize) * view.devicePixelRatio,
      logicalConstraints: BoxConstraints.tight(logicalSize),
      devicePixelRatio: view.devicePixelRatio,
    ),
  );

  final pipelineOwner = PipelineOwner();
  final buildOwner = BuildOwner(focusManager: FocusManager());

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

  final rootElement = RenderObjectToWidgetAdapter<RenderBox>(
    container: repaintBoundary,
    child: rb,
  ).attachToRenderTree(buildOwner);

  buildOwner.buildScope(rootElement);
  buildOwner.finalizeTree();

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

  final image = await repaintBoundary.toImage(
    pixelRatio: imageSize.width / logicalSize.width,
  );
  final bytes = await image.toByteData(format: ImageByteFormat.png);
  buildOwner.finalizeTree();
  if (bytes == null) {
    debugPrint(
      'StyleController.addWidgetImage: failed to convert widget to '
      'image bytes for id "$id".',
    );
    return;
  }
  await addImage(id, bytes.buffer.asUint8List());
}