I need to take a screenshot of the current screen or widget and I need to write it into a file.
How to take a screenshot of the current widget - Flutter
Asked Answered
I tried and found the solution,
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/rendering.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static GlobalKey previewContainer = GlobalKey();
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return RepaintBoundary(
key: previewContainer,
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
ElevatedButton(
onPressed: takeScreenShot,
child: const Text('Take a Screenshot'),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
)
);
}
Future<void> takeScreenShot() async{
final boundary = previewContainer.currentContext!.findRenderObject() as RenderRepaintBoundary;
final image = await boundary.toImage();
final directory = (await getApplicationDocumentsDirectory()).path;
final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
final pngBytes = byteData?.buffer.asUint8List();
final imgFile =File('$directory/screenshot.png');
imgFile.writeAsBytes(pngBytes!);
}
}
Finally check your application directory You will find screenshot.png !!
I am using this code but not take a full-screen screenshot –
Tawnytawnya
@Tawnytawnya me too. I've checked this github.com/flutter/flutter/issues/17687 but the bug still exists. –
Trituration
image quality is bad. Is there anyway to control the quality of the screenshot? –
Millais
Increasing the pixel ratio should improve the quality of the output image. ui.Image image = await boundary.toImage(pixelRatio: 2.0); –
Merbromin
Is their any way to take screenshot in flutter web application by same method or any other method? I try it but didn't work. –
Palladian
Unhandled Exception: type 'RenderSemanticsAnnotations' is not a subtype of type 'RenderRepaintBoundary' –
Swigart
how can we create jpg image? png image is transparent and mixed with background. Please share any suggestion. –
Draughty
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)); –
Hectogram
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);
}
I 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? –
Phonogram
@Phonogram I don't think it's possible, simply because those items are not even built, so no one knows how they would look like. –
Galen
@MarcinSzałek , are you absolutely sure about that? It's important enough that I'm posting a question about it: #57584465 –
Nadenenader
how can we create jpg image? png image is transparent and mixed with background. Please share any suggestion. –
Draughty
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);
});
});
}
I tried this code. It works but produces a low-quality screenshot. It's kindof blurry. Any idea how to make it sharp? –
Jannjanna
it works also in 2022 thanks –
Culbreth
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 –
Niggerhead
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
This takes the screenshot of my entire screen and not the emulator. –
Momus
This doesn't capture a widget. It only takes a screenshot of the device's screen. –
Sumatra
It gives me error:
Screenshot not supported for Linux.
–
Connors © 2022 - 2024 — McMap. All rights reserved.