【问题标题】:RenderRepaintBoundary to image without adding Widget to screenRenderRepaintBoundary 到图像而不将 Widget 添加到屏幕
【发布时间】:2019-08-03 16:25:57
【问题描述】:

我正在尝试从 Widget 导出图像而不将此 Widget 添加到屏幕。

这甚至可能吗?

我已经通过添加到可滚动容器成功导出它,现在我想渲染它而不将其添加到屏幕并将其保存到临时文件以进行共享。

我认为那里应该有一个“油漆”电话,但无法弄清楚确切的位置。

这是我的代码:

var shareImage = await ShareImageWidget.builder(context,
item: item, definition: definition);
var widget = shareImage.build(context);
var repaint = RepaintBoundary.wrap(widget, 0);
var render = RenderRepaintBoundary(child:repaint.createRenderObject(context));
ui.Image image = await render.toImage(pixelRatio: 1.0);
ByteData byteData = await image.toByteData(format:ui.ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
var bs64 = base64Encode(pngBytes);
var dir = await getTemporaryDirectory();

【问题讨论】:

  • 不幸的是,当您使用它时,它会引发与不透明度为 0 的小部件相同的错误。" flutter: 'package:flutter/src/rendering/proxy_box.dart': 断言失败:行2882​​ pos 12: '!debugNeedsPaint': 不正确。"
  • @GünterZöchbauer
  • 你有没有找到一个解决方案来绘制一个小部件而不显示它?
  • 嘿卢卡,我没有。最后用另一个小部件覆盖了这个小部件。

标签: dart flutter


【解决方案1】:

您可以使用 Transform.translate 小部件将小部件移出屏幕。 Transform 在绘制之前移动小部件。

【讨论】:

    【解决方案2】:

    我正在使用这里的函数:

    How to create an image from a widget in Flutter-web?

    此功能允许您将小部件转换为图像,而无需担心将这些小部件隐藏在屏幕上。 最近,这也开始在网络上运行。

    【讨论】:

      【解决方案3】:

      示例:

      /// Creates an image from the given widget by first spinning up a element and render tree,
      /// then waiting for the given [wait] amount of time and then creating an image via a [RepaintBoundary].
      /// 
      /// The final image will be of size [imageSize] and the the widget will be layout, ... with the given [logicalSize].
      Future<Uint8List> createImageFromWidget(Widget widget, {Duration wait, Size logicalSize, Size imageSize}) async {
        final RenderRepaintBoundary repaintBoundary = RenderRepaintBoundary();
      
        logicalSize ??= ui.window.physicalSize / ui.window.devicePixelRatio;
        imageSize ??= ui.window.physicalSize;
      
        assert(logicalSize.aspectRatio == imageSize.aspectRatio);
      
        final RenderView renderView = RenderView(
          window: null,
          child: RenderPositionedBox(alignment: Alignment.center, child: repaintBoundary),
          configuration: ViewConfiguration(
            size: logicalSize,
            devicePixelRatio: 1.0,
          ),
        );
      
        final PipelineOwner pipelineOwner = PipelineOwner();
        final BuildOwner buildOwner = BuildOwner();
      
        pipelineOwner.rootNode = renderView;
        renderView.prepareInitialFrame();
      
        final RenderObjectToWidgetElement<RenderBox> rootElement = RenderObjectToWidgetAdapter<RenderBox>(
          container: repaintBoundary,
          child: widget,
        ).attachToRenderTree(buildOwner);
      
        buildOwner.buildScope(rootElement);
      
        if (wait != null) {
          await Future.delayed(wait);
        }
      
        buildOwner.buildScope(rootElement);
        buildOwner.finalizeTree();
      
        pipelineOwner.flushLayout();
        pipelineOwner.flushCompositingBits();
        pipelineOwner.flushPaint();
      
        final ui.Image image = await repaintBoundary.toImage(pixelRatio: imageSize.width / logicalSize.width);
        final ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
      
        return byteData.buffer.asUint8List();
      }
      
      

      参考:https://github.com/flutter/flutter/issues/40064#issuecomment-620081426

      有一个包有这个功能:https://pub.dev/packages/screenshot#capturing-widgets-that-are-not-in-the-widget-tree

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-07-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多