Skip to content

Instantly share code, notes, and snippets.

@kangabru kangabru/screenshot.dart
Last active Jun 21, 2020

Embed
What would you like to do?
Allows you extract an image of specific widgets within your app. Includes the ability to ignore certain widgets and to crop the final image.
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
// Note: [ui.Image] represents the lower level image data while [Image] represents a renderable image.
/// Provides the ability to take screenshots of specific widgets.
mixin Screenshot<T extends StatefulWidget> on State<T> {
static GlobalKey _key = new GlobalKey();
/// Wrap this around widget you wish to screenshot.
Widget screenshotThis(Widget child) => RepaintBoundary(key: _key, child: child);
/// Returns the screenshot of the widgets wrapped with [screenshotThis].
/// Applies an optional background and crop to the final image.
Future<ScreenshotData> takeScreenshot({Color background, Rect crop}) async {
var imageDataRaw = await _getScreenshotData();
var imageData = await _updateImage(imageDataRaw, background, crop);
return _convertDataToImage(imageData);
}
/// Returns the raw image of the widgets to screenshot.
Future<ui.Image> _getScreenshotData() async {
RenderRepaintBoundary boundary = _key.currentContext.findRenderObject();
return boundary.toImage();
}
/// Converts the raw image into a renderable form.
Future<ScreenshotData> _convertDataToImage(ui.Image imageData) async {
var byteData = await imageData.toByteData(format: ui.ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
var image = Image.memory(pngBytes);
return ScreenshotData(image, pngBytes);
}
/// Processes an image with an optional background color and crop
Future<ui.Image> _updateImage(ui.Image image, [Color background, Rect crop]) {
var pictureRecorder = new ui.PictureRecorder();
Canvas canvas = new Canvas(pictureRecorder);
canvas.drawPaint(Paint()..color = background ?? Colors.transparent);
// No crop provided so render the full image
if (crop == null) {
int width = image.width, height = image.height;
canvas.drawImage(image, Offset.zero, Paint());
return pictureRecorder.endRecording().toImage(width, height);
}
// Crop the image by extracting the crop rect and moving to the top left
final width = crop.width, height = crop.height;
var dest = Rect.fromLTWH(0, 0, width, height);
canvas.drawImageRect(image, crop, dest, Paint());
return pictureRecorder.endRecording().toImage(width.floor(), height.floor());
}
}
/// Contains a renderable Image and the raw image bytes.
class ScreenshotData {
final Image image;
final Uint8List pngBytes;
ScreenshotData(this.image, this.pngBytes);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.