I need to take a screenshot of the current screen or widget and I need to write it into a file.
Asked
Active
Viewed 4.8k times
4 Answers
40
I tried and found the solution,
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static GlobalKey previewContainer = new GlobalKey();
int _counter = 0;
void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: previewContainer,
child: new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
new RaisedButton(
onPressed: takeScreenShot,
child: const Text('Take a Screenshot'),
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
)
);
}
takeScreenShot() async{
RenderRepaintBoundary boundary = previewContainer.currentContext.findRenderObject();
ui.Image image = await boundary.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData.buffer.asUint8List();
print(pngBytes);
File imgFile =new File('$directory/screenshot.png');
imgFile.writeAsBytes(pngBytes);
}
}
Finally check your application directory You will find screenshot.png !!

Prabhu
- 1,135
- 1
- 12
- 14
-
1I am using this code but not take a full-screen screenshot – mr.hir Jan 10 '19 at 06:33
-
@mr.hir me too. I've checked this https://github.com/flutter/flutter/issues/17687 but the bug still exists. – Rust Fisher Mar 13 '19 at 15:44
-
1image quality is bad. Is there anyway to control the quality of the screenshot? – ibrahim Feb 27 '20 at 08:59
-
1Increasing the pixel ratio should improve the quality of the output image. ui.Image image = await boundary.toImage(pixelRatio: 2.0); – Vikalp Mar 06 '20 at 20:35
-
1Is their any way to take screenshot in flutter web application by same method or any other method? I try it but didn't work. – Abdullah Khan Mar 31 '20 at 18:04
-
Unhandled Exception: type 'RenderSemanticsAnnotations' is not a subtype of type 'RenderRepaintBoundary' – TSR Sep 22 '20 at 14:30
-
how can we create jpg image? png image is transparent and mixed with background. Please share any suggestion. – Kamlesh Oct 23 '20 at 12:52
-
This is awesome and better than the screenshot pubdev package - but - you need to put in await or it will only work occasionally :) await imgFile.writeAsBytes(pngBytes.buffer .asUint8List(pngBytes.offsetInBytes, pngBytes.lengthInBytes)); – psimons Apr 01 '21 at 15:32
30
let's say you want to take a screenshot of the FlutterLogo
widget . wrap it in a RepaintBoundary
with will creates a separate display list for its child . and provide with a key
var scr= new GlobalKey();
RepaintBoundary(
key: scr,
child: new FlutterLogo(size: 50.0,))
and then you can get the pngBytes
by converting the boundary to an image
takescrshot() async {
RenderRepaintBoundary boundary = scr.currentContext.findRenderObject();
var image = await boundary.toImage();
var byteData = await image.toByteData(format: ImageByteFormat.png);
var pngBytes = byteData.buffer.asUint8List();
print(pngBytes);
}

Raouf Rahiche
- 28,948
- 10
- 85
- 77
-
7I have a question => my widget Listview has more than 10 items, so the screen can't show all items and the capture image is only showing what we have in the screen. Is any method to capture the whole ListView even if the items is not showing on the screen? – GPH Nov 16 '18 at 06:27
-
@GPH I don't think it's possible, simply because those items are not even built, so no one knows how they would look like. – Marcin Szałek Mar 16 '19 at 08:52
-
@MarcinSzałek , are you absolutely sure about that? It's important enough that I'm posting a question about it: https://stackoverflow.com/questions/57583965/flutter-dart-capture-entire-partially-offscreen-widget-as-image – A. L. Strine Aug 21 '19 at 03:14
-
how can we create jpg image? png image is transparent and mixed with background. Please share any suggestion. – Kamlesh Oct 23 '20 at 12:53
8
here's the solution for flutter 2.0+ method for screenshot and share it on social media
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'dart:ui' as ui;
import 'package:path_provider/path_provider.dart';
import 'package:share/share.dart';
GlobalKey previewContainer = new GlobalKey();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: RepaintBoundary(
key: previewContainer,
child: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Take Screen Shot',
),
],
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: _captureSocialPng,
tooltip: 'Increment',
child: Icon(Icons.camera),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
Future<void> _captureSocialPng() {
List<String> imagePaths = [];
final RenderBox box = context.findRenderObject() as RenderBox;
return new Future.delayed(const Duration(milliseconds: 20), () async {
RenderRepaintBoundary? boundary = previewContainer.currentContext!
.findRenderObject() as RenderRepaintBoundary?;
ui.Image image = await boundary!.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
File imgFile = new File('$directory/screenshot.png');
imagePaths.add(imgFile.path);
imgFile.writeAsBytes(pngBytes).then((value) async {
await Share.shareFiles(imagePaths,
subject: 'Share',
text: 'Check this Out!',
sharePositionOrigin: box.localToGlobal(Offset.zero) & box.size);
}).catchError((onError) {
print(onError);
});
});
}

sanchit
- 149
- 2
- 3
-
1I tried this code. It works but produces a low-quality screenshot. It's kindof blurry. Any idea how to make it sharp? – Salahuddin Jun 07 '22 at 21:48
-
1
-
Hey! i got an error when we cast as RenderRepaintBoundary?, says that 'type 'RenderFlex' is not a subtype of type 'RenderRepaintBoundary?' in type cast' when creating the boundary – Jocgomez Oct 05 '22 at 15:39
2
Run
flutter screenshot
It will take the screenshot from your connected device and save that to your folder in which you are doing development it will save flutter_01.jpg like that in your folder
-
1
-
This doesn't capture a widget. It only takes a screenshot of the device's screen. – Wilson Wilson Mar 04 '21 at 15:39
-