How to take a screenshot in Flutter.

0
366
Post banner made with canva

Hello everyone and welcome to a brand new tutorial series on Flutter. Today we’re going to learn how to take a screenshot in our app using Flutter.

A few days back, I was working on a payment application with flutter, so I wanted to able to generate a receipt inform of a screenshot to users after a successful transaction, so that’s how I started searching on how to take the screenshot and found a good solution for the idea. So I thought to myself, why not write an article about it, so others can just spend a few minutes integrating what took me a few hours to implement. So in this article, I would be teaching you how you can take a screenshot and save it to your gallery in flutter using some flutter package which would be specified later in this write-up, Stay tune.

So, why not just use the default phone screenshot? Yeah, that would have been easier no code required but in some situations, you will want the button to take the screenshot to be on your app or you just want to capture a specific part of the app/screen, flutter has made it easier with the help of RepaintBoundary widget.

So, if you are here, then I’m assuming that you already know flutter, that you use flutter and you’ve got it installed on your machine already and you know how to start/create a project. It’s always a privilege to upgrade your skillsets through my write-ups. So let’s jump in.

The first thing you need to know is whatever widget you want to capture is where you will wrap RepaintBoundary with:

Example 1: If you want to capture the whole Scaffold just wrap it with RepaintBoundary and provide it with a special key

var scr = GlobalKey();
RepaintBoundary(
    key: scr,
    child: Scaffold());

Example 2: If you want to only capture a part of the screen may be the flutter logo just wrap it RepaintBoundary and provide it with a separate key with a different name *scr1*

var scr1 = GlobalKey();
Column(
    children: <Widget>[
       RepaintBoundary(
         key: scr1,
         child: FlutterLogo(size: 50.0),
        ),
       Text(
         'You have pushed the button this many times:',),
]),

In the example above we’re only capturing the flutter logo, as you can see we only wrap the FlutterLogo with the RepaintBoundary widget so the Text input won’t be captured.

So, after wrapping it with RepaintBoundary then you can get the pngBytes by converting the boundary to an image

takescrshot() async {
  RenderRepaintBoundary boundary = scr.currentContext.findRenderObject(); // the key provided
  var image = await boundary.toImage();
  var byteData = await image.toByteData(format: ImageByteFormat.png);
  var pngBytes = byteData.buffer.asUint8List();
  print(pngBytes);
  }

if you check the takescrshot() function very well you will see we only pass one key provided which is scr, so imagine we have two buttons for taking the screenshot: i) take the full screenshot ii) take a screenshot of another widget wrapped with the Repaint widget.

Full Example code:

import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

class HomePage extends StatefulWidget {
  HomePage({Key key}) : super(key: key);

  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  var scr = GlobalKey();
  var scr1 = GlobalKey();
  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      key: scr,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Screenshot Example'),
          centerTitle: true,
          elevation: 0,
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              RepaintBoundary(
                  key: scr1,
                  child: FlutterLogo(
                    size: 100,
                  )),
              SizedBox(height: 10),
              Text(
                'You have pushed the button this many times:',
              ),
              Text(
                '$_counter',
                style: Theme.of(context).textTheme.headline4,
              ),
              MaterialButton(
                onPressed: () {
                  takescrshot();
                },
                child: Text('Take full screen'),
                color: Colors.blue,
              ),
              MaterialButton(
                onPressed: () {
                  takescrshot1();
                },
                child: Text('Take full screen'),
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),
    );
  }

  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 *********************8 scr');
  }

  takescrshot1() async {
    RenderRepaintBoundary boundary = scr1.currentContext.findRenderObject();
    var image = await boundary.toImage();
    var byteData = await image.toByteData(format: ImageByteFormat.png);
    var pngBytes = byteData.buffer.asUint8List();
    print('$pngBytes *********************8 scr1');
  }
}

So after we have captured the screen we need to save it to the phone memory because that’s the main essence of the whole stuff, so to do that we are going to make use of two packages

  1. image_gallery_saver: For saving the images into the gallery
  2. permission_handler: storage permission handler and many other android permissions

We need to initialize the storage permission first, so users must allow permission to save files to their device to be able to save the screenshot.

Before initialization, we need to ask for permission from Android to be able to read and write to external storage, so to do that navigate to {your-app-name}\android\app\src\main\AndroidManifest.xml and paste 👇

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

Then, our method for _requestPermission() in the main.dart file;

_requestPermission() async {
  Map<Permission, PermissionStatus> statuses = await [
    Permission.storage,
  ].request();
final info = statuses[Permission.storage].toString();
  print('$info');
}

Let also call the _requestPermission() in initState so users would have allowed the request before viewing the page

@override
  void initState() {
    super.initState();
    _requestPermission();
  }

So, you should see this pop-up when you restart the application 👇

Pop-up screenshot

After clicking on allow then we can move on to the next stage.

So, let modified the takescrshot functions now

takescrshot() async {
    RenderRepaintBoundary boundary = scr.currentContext.findRenderObject();
    if (boundary.debugNeedsPaint) {
      Timer(Duration(seconds: 1), () => saveScreen());
      return null;
    }
    ui.Image image = await boundary.toImage();
    ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    final result =
        await ImageGallerySaver.saveImage(byteData.buffer.asUint8List());
    print('$byteData ********** Saved to gallery *********** $result');
}

Also, make sure you import the necessary packages

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:permission_handler/permission_handler.dart';

So, just create two buttons that will take the different screenshots

Row(
    mainAxisAlignment: MainAxisAlignment.spaceAround,
    children: [
      MaterialButton(
        onPressed: () {
          takescrshot();
        },
        child: Text('The fullscreen shot'),
        color: Colors.blue,
      ),
      MaterialButton(
          onPressed: () {
            takescrshot1();
          },
          child: Text('Only flutter logo shot'),
          color: Colors.red),
  ],
 ),

Screenshots:

Screentshots

I hope you have learned something, kindly press the clap button as many time you want if you enjoy it, and feel free to ask a question. Thanks for reading

Full Source code 👇 and show some ❤️ by starring the repo ⭐

GitHub – acctgen1/Flutter-Tutorials-Projects

Join Flutter Developer Community: Telegram Facebook WhatsApp

Let’s connect each other online:
GithubHashnodeFacebook, TwitterInstagramYoutubeMediumLinkedIn, Techpadi, etc.

Read also: Convert your website into an application in a few minutes(Flutter Webview).

Happy Fluttering 👩‍💻

Leave a Reply