需求
需要将相关的widget转成图片。
实现
通过 RenderRepaintBoundry.toImage()来获取Image数据,pixelRatio
属性可以调整图片的清晰度。
RenderRepaintBoundry.toImage()
内部调用offsetLayer.toImage
方法;offsetLayer.toImage
调用scene.toImage
方法,交给底层处理。
Future<ui.Image> toImage({ double pixelRatio = 1.0 }) {
assert(!debugNeedsPaint);
final OffsetLayer offsetLayer = layer! as OffsetLayer;
return offsetLayer.toImage(Offset.zero & size, pixelRatio: pixelRatio);
}
...
Future<ui.Image> toImage(Rect bounds, { double pixelRatio = 1.0 }) async {
....
try {
// Size is rounded up to the next pixel to make sure we don't clip off
// anything.
return await scene.toImage(
(pixelRatio * bounds.width).ceil(),
(pixelRatio * bounds.height).ceil(),
);
} finally {
scene.dispose();
}
}
}
...
String? _toImage(int width, int height, _Callback<_Image?> callback) native 'Scene_toImage';
实现代码
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey genKey = GlobalKey();
String? imagePath;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'Create an Image from Widget',
),
RepaintBoundary(
key: genKey,
child: const ListTile(
leading: CircleAvatar(),
title: Text("Hello,friend"),
),
),
if (imagePath != null) Image.file(File(imagePath!))
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _takePicture,
tooltip: 'start',
child: const Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Future<void> _takePicture() async {
RenderRepaintBoundary? boundary =
genKey.currentContext?.findRenderObject() as RenderRepaintBoundary?;
ui.Image? image = await boundary?.toImage(pixelRatio: 5);
ByteData? byteData =
await image?.toByteData(format: ui.ImageByteFormat.png);
final directory = (await getApplicationDocumentsDirectory()).path;
File? imgFile = File('$directory/photo.png');
Uint8List? pngBytes = byteData?.buffer.asUint8List();
imgFile.writeAsBytes(pngBytes!);
setState(() {
imagePath = imgFile.path;
});
}
源码
https://github.com/sayhellotogithub/flutter-widget-to-image
参考
https://medium.com/flutter-community/export-your-widget-to-image-with-flutter-dc7ecfa6bafb
https://api.flutter.dev/flutter/rendering/RenderRepaintBoundary/toImage.html
https://stackoverflow.com/questions/41957086/creating-raw-image-from-widget-or-canvas