目的是为了实现 高德地图Marker自定义,坑爹的只支持 本地素材 和 Uint8List,所以只能转换了。

网上搜 Widget 转 Image,基本都是需要在 build 内部实现,然后赋值一个key,生成 Uint8List。也就是将已经显示到页面上的 Widget 转成图片。
而地图的 Marker 需要在加载数据库时执行,显然不可行。

直接搜“高德地图Marker自定义”,还能搜到几篇文章。基本都是同一个答案,代码如下:

  static Future<ByteData> widgetToImage(
    Widget widget, {
    Alignment alignment = Alignment.center,
    Size size = const Size(double.maxFinite, double.maxFinite),
    double devicePixelRatio = 1.0,
    double pixelRatio = 1.0,
  }) async {
    RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();

    RenderView renderView = RenderView(
      child: RenderPositionedBox(alignment: alignment, child: repaintBoundary),
      configuration: ViewConfiguration(
        size: size,
        devicePixelRatio: devicePixelRatio,
      ),
      view: WidgetsBinding.instance.platformDispatcher.views.first,
    );

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

    BuildOwner buildOwner = BuildOwner(focusManager: FocusManager());
    RenderObjectToWidgetElement rootElement = RenderObjectToWidgetAdapter(
      container: repaintBoundary,
      child: widget,
    ).attachToRenderTree(buildOwner);
    buildOwner.buildScope(rootElement);
    buildOwner.finalizeTree();

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

    ui.Image image = await repaintBoundary.toImage(pixelRatio: pixelRatio);
    ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);

    return byteData!;
  }

然后直接使用就会成这样,样式根本显示不出来


最终真是皇天不负苦心人,找到了坑。

问题点在这里:

调用的时候,一定要手动给于 Size 大小

    var byteData = await MapImageUtil.widgetToImage(widget, size: const Size(300, 400));
    return BitmapDescriptor.fromBytes(byteData.buffer.asUint8List());

真的是坑啊