如何在Flutter中将小部件绘制到屏幕外

4
我正在寻找一种解决方案,可以在一个单独的图形管道中绘制Flutter小部件树,这将永远不会在屏幕上显示。我想能够定义任何大小的宽度/高度约束,而不受显示器限制。
目标是获取此小部件的PNG图像,该图像不依赖于设备,并将其发送到打印机。我知道可以使用RepaintBoundary来构建图像,但这仅适用于在屏幕上显示的内容。
我尝试了类似以下的方法,但没有成功:
Future<void> capture(BuildContext context, Widget widget) async {
  final rect = Rect.fromLTWH(0, 0, 200, 200);

  final root = OffscreenPainter(
      size: Size(200, 200),
      child: ConstrainedBox(
        constraints: BoxConstraints.tightFor(width: 200, height: 200),
        child: widget,
      ));

  final ro = root.createRenderObject(context);

  final el = root.createElement();
  // el.activate();
  el.attachRenderObject(ro);
  final o = PipelineOwner();

  // ro.attach(o);
  o.rootNode = ro;
  ro.scheduleInitialLayout();
  final rootLayer = OffsetLayer();
  rootLayer.attach(o);

  ro.scheduleInitialPaint(rootLayer);

  el.updateChildren();
  ro.layout(BoxConstraints(maxWidth: rect.width, maxHeight: rect.height));

  o.flushLayout();
  o.flushCompositingBits();
  o.flushPaint();
  final im = await ro.toImage();
  final bd = await im.toByteData(format: ImageByteFormat.png);
  final f = File('image.png');
  f.writeAsBytesSync(bd.buffer.asUint8List());
  print('saved to ${f.absolute}');
}

class OffscreenPainter extends SingleChildRenderObjectWidget {
  /// Creates a widget that isolates repaints.
  const OffscreenPainter({Key key, Widget child, @required this.size})
      : super(key: key, child: child);

  final Size size;

  @override
  RenderOffscreenPainter createRenderObject(BuildContext context) =>
      RenderOffscreenPainter(size);
}

class RenderOffscreenPainter extends RenderRepaintBoundary {
  RenderOffscreenPainter(this._size);

  final Size _size;

  @override
  void performLayout() {
    if (child != null) {
      child.layout(BoxConstraints.tight(_size));
      size = child.size;
    } else {
      size = _size;
    }
  }
}


你尝试过使用Overlays吗?https://api.flutter.dev/flutter/widgets/Overlay-class.html - Stefano Saitta
叠加层仍然是一个小部件,无法在屏幕外绘制。 - Dav
1个回答

2
你可以使用Transform小部件将你的小部件推到屏幕外。根据文档,Transform.translate在绘制小部件之前移动小部件。

在这个例子中,我在底部导航栏中添加了一个图标并将其向下移动。它不会显示,但我仍然可以访问RepaintBoundary。

Transform.translate(
  offset: Offset(0,200),
  child: RepaintBoundary(
    key: iconKey,
    child: IconButton(icon: Icon(Icons.star),
        onPressed: () {
          // Do something
        }),
  ),
),

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接