【发布时间】:2022-01-04 15:04:26
【问题描述】:
我正在尝试将小部件导出为图像,它比实际视口更宽。
我找到了这个方法:
Future<Uint8List?> createImageFromWidget(Widget widget,
{Size? logicalSize, Size? imageSize}) async {
final repaintBoundary = RenderRepaintBoundary();
logicalSize ??= ui.window.physicalSize / ui.window.devicePixelRatio;
imageSize ??= ui.window.physicalSize;
assert(logicalSize.aspectRatio == imageSize.aspectRatio);
final renderView = RenderView(
window: ui.window,
child: RenderPositionedBox(child: repaintBoundary),
configuration: ViewConfiguration(
size: logicalSize,
),
);
final pipelineOwner = PipelineOwner();
final buildOwner = BuildOwner(focusManager: FocusManager());
pipelineOwner.rootNode = renderView;
renderView.prepareInitialFrame();
final rootElement = RenderObjectToWidgetAdapter<RenderBox>(
container: repaintBoundary,
child: widget,
).attachToRenderTree(buildOwner);
buildOwner.buildScope(rootElement);
buildOwner.finalizeTree();
pipelineOwner.flushLayout();
pipelineOwner.flushCompositingBits();
pipelineOwner.flushPaint();
final image = await repaintBoundary.toImage(
pixelRatio: imageSize.width / logicalSize.width);
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
if (byteData == null) return null;
return byteData.buffer.asUint8List();
}
据我了解,此方法在新的 Offscreen-Widgettree 中构建引用的 Widget,并将视口大小设置为需要导出的 Widget 的大小。
这种方法本身有效,但这是我的问题:
我正在引用需要由GlobalKey 导出的Widget。
所以它看起来像这样:
Repaintboundary(
key: myGlobalKey,
child : WidgetIWantToExport()
);
void exportWidget(){
final currentWidgetSize = myGlobalKey.currentContext!.size!;
final keyWidget = myGlobalKey.currentWidget!;
final pngBytes = await createImageFromWidget(
keyWidget,
logicalSize: Size(currentWidgetSize.width, currentWidgetSize.height),
imageSize: Size(currentWidgetSize.width, currentWidgetSize.height),
);
//exporting bytes
}
所以当我运行这个方法时,.attachToRenderTree() 会抛出一个错误:'_elements.contains(element)': is not true. ... Duplicate GlobalKey detected in widget tree.
所以我假设问题是,它试图在新的 RenderTree 中构建一个具有相同 GobalKey 的小部件,这会引发此错误。
我该如何解决这个问题?
【问题讨论】:
标签: flutter dart flutter-layout