Open In App

Flutter- Screenshot Package

Last Updated : 12 Jan, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Flutter is a popular framework by Google which is growing fast with its growing community. The Flutter has created a buzz through its libraries, making the development fast-paced.

Nowadays, everyone loves to take screenshots. If your application involves the use of screenshots, Flutter got a package for it. Not only for this purpose, but it is very helpful in the testing and debugging process. The fast-changing data screens can be captured through screenshots, and doing this manually is a boring task as well as time-wasting. The screenshot package automates the process of capturing the widgets you want to capture and storing them somewhere.  If you want your user to capture only certain widgets of the screen, not an entire screen, this package is here to help you. In this article, we will implement a screenshot package in Flutter.

Follow the article to see how to do screenshot work in Flutter.

Step 1: Add the following dependency in your pubspec.yaml file.

Add the given dependency in pubspec.yaml file.

Dart




dependencies:
  screenshot: ^1.2.3


 
Now click on the pub get to configure it. Or add dependency directly to the pubspec.yaml from the terminal by writing the below code in the terminal.

flutter pub add screenshot

Step 2: Import the library. 

Dart




import 'package:screenshot/screenshot.dart';


 
Step 3: Navigate to main.dart.

First, move to the main.dart and modify the main function. When you create a Flutter app, some lines of code are already written for you. We are going to keep it. Remove the stateless widget MyHomePage from the code, and keep only the below-shown code. Then give our first screen of the app in the home: HomePage(). 

Dart




import 'package:flutter/material.dart';
import 'home.dart';
 
void main() {
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
 
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
         
        primarySwatch: Colors.green,
      ),
      home: HomePage(),
    );
  }
}


 
Step 4: Declare StatefulWidget() for HomePage() class

Create another dart file home.dart where we will create a stateful HomePage() class. In that HomePage() class, we have given screenshotController. After that, we have declared Scaffold() in which we have declared appbar that consists of the title of the app – “Screenshot Demo App”. In the body section, we have declared the Screenshot widget that takes screenshotController as a parameter wrapped with the center widget. 

We have created two ElevatedButton, one shows the decreasing timer and the other is an increasing timer. We can take a screenshot of both the buttons by pressing another button that shows Capture above Widget. This will show the captured widget on a different screen. Remember, we need to wrap all the widgets inside the Screenshot widget whose screenshot you want. We have wrapped both the timers as well as their respective texts inside the Screenside widget. At the respective particular values, both timers will stop, and by clicking the refresh button their values will be reset. 

Sometimes, it takes time to load the widgets on the screen, and they are invisible until they are not on the screen. But with this library, we can even capture them. To show that, we have created an invisible widget, that is captured when another button that shows Capture An Invisible Widget is pressed. This will show the invisible widget on another screen.

Dart




import 'dart:async';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
 
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
 
class _HomePageState extends State<HomePage> {
   
  // Create an instance of ScreenshotController
  ScreenshotController screenshotController = ScreenshotController();
 
  @override
  void initState() {
    super.initState();
  }
 
  // create a variable of type Timer
  late Timer _timer;
  int _start = 0;
  int _startTwo = 61;
 
  // function to increment the timer until
  // 61 and set the state
  void increasingStartTimer() {
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_start > 60) {
            timer.cancel();
          } else {
            _start = _start + 1;
          }
        },
      ),
    );
  }
 
  // function to decrease the timer
  // until 1 and set the state
  void decreasingStartTimer() {
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_startTwo < 0) {
            timer.cancel();
          } else {
            _startTwo = _startTwo - 1;
          }
        },
      ),
    );
  }
 
  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("GeeksForGeeks"),
        centerTitle: true,
      ),
      body: Center(
        child: Column(
          children: [
            SizedBox(height: 30),
            Screenshot(
              controller: screenshotController,
              child: Column(
                children: [
                  Text("Decreasing Timer : "),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      padding: const EdgeInsets.all(30.0),
                      decoration: BoxDecoration(
                        border:
                            Border.all(color: Colors.blueAccent, width: 5.0),
                        color: Colors.amberAccent,
                      ),
                      child: Text(_startTwo.toString())),
                  SizedBox(
                    height: 25,
                  ),
                  Text("Increasing Timer : "),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      padding: const EdgeInsets.all(30.0),
                      decoration: BoxDecoration(
                        border:
                            Border.all(color: Colors.blueAccent,
                                       width: 5.0),
                        color: Colors.amberAccent,
                      ),
                      child: Text("$_start")),
                ],
              ),
            ),
            ElevatedButton(
              onPressed: () {
                 
                // invoking both functions for timer to start
                increasingStartTimer();
                decreasingStartTimer();
              },
              child: Text("start"),
            ),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    _start = 0;
                    _startTwo = 61;
                  });
                },
                child: Text("Refresh")),
            ElevatedButton(
              child: Text(
                'Capture Above Widget',
              ),
              onPressed: () {
                 
                // invoking capture on
                // screenshotController
                screenshotController
                    .capture(delay: Duration(milliseconds: 10))
                    .then((capturedImage) async {
                       
                  // showing the captured widget
                  // through ShowCapturedWidget
                  ShowCapturedWidget(context,
                                     capturedImage!);
                }).catchError((onError) {
                  print(onError);
                });
              },
            ),
            ElevatedButton(
              child: Text(
                'Capture An Invisible Widget',
              ),
              onPressed: () {
                var container = Container(
                    padding: const EdgeInsets.all(30.0),
                    decoration: BoxDecoration(
                      border: Border.all(color: Colors.blueAccent,
                                         width: 5.0),
                      color: Colors.pink,
                    ),
                    child: Text(
                      "This is an invisible widget",
                      style: Theme.of(context).textTheme.headline6,
                    ));
                 
                // capturing all the widgets
                // that are invisible
                screenshotController
                    .captureFromWidget(
                        InheritedTheme.captureAll(
                            context, Material(child: container)),
                        delay: Duration(seconds: 1))
                    .then((capturedImage) {
                       
                  // showing the captured invisible widgets
                  ShowCapturedWidget(context, capturedImage);
                });
              },
            ),
          ],
        ),
      ),
    );
  }
 
  // function to show captured widget
  Future<dynamic> ShowCapturedWidget(
      BuildContext context, Uint8List capturedImage) {
    return showDialog(
      useSafeArea: false,
      context: context,
      builder: (context) => Scaffold(
        appBar: AppBar(
          title: Text("Captured widget screenshot"),
        ),
        body: Center(
            child: capturedImage != null
                ? Image.memory(capturedImage)
                : Container()),
      ),
    );
  }
}


The captured screenshots: 

Save Screenshots to Gallery:

To save screenshots in the gallery, we need to write additional code for them in the previously shown code. We will be using a package – image_gallery_saver for this purpose. Add below dependency in pubspec.yaml file.

Dart




dependencies:
     image_gallery_saver: '^1.7.1'


 Now, run pub get to configure it, and we need to import the library in our home.dart file.  

Dart




import 'package:image_gallery_saver/image_gallery_saver.dart';


 Now, we need to create a function to which we will pass captured images to save to the Gallery. 

Dart




_saved(Uint8List image) async {
   final result = await ImageGallerySaver.saveImage(image);
   print("File Saved to Gallery");
 }


Here, we created an asynchronous function that takes Uint8List type data as input. We can save images as files or bytes but we need to convert them to a specific type. Since the screenshots captured are in bytes format, we are using the saveImage function to save the screenshot. Now, we need to call the function, we will be calling this function each time we capture a screenshot, both of a visible widget and an invisible widget. See the complete code of the home.dart below.

Complete Source Code:

Dart




import 'dart:async';
import 'dart:typed_data';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'package:flutter/material.dart';
import 'package:screenshot/screenshot.dart';
 
class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}
 
class _HomePageState extends State<HomePage> {
   
  // Create an instance of ScreenshotController
  ScreenshotController screenshotController = ScreenshotController();
 
  @override
  void initState() {
    super.initState();
  }
 
   
  late Timer _timer;
  int _start = 0;
  int _startTwo = 61;
 
  void increasingStartTimer() {
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_start > 60) {
            timer.cancel();
          } else {
            _start = _start + 1;
          }
        },
      ),
    );
  }
 
  void decreasingStartTimer() {
    const oneSec = const Duration(seconds: 1);
    _timer = new Timer.periodic(
      oneSec,
      (Timer timer) => setState(
        () {
          if (_startTwo < 0) {
            timer.cancel();
          } else {
            _startTwo = _startTwo - 1;
          }
        },
      ),
    );
  }
 
  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }
 
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Screenshot Demo App"),
      ),
      body: Center(
        child: Column(
          children: [
            SizedBox(height: 30),
            Screenshot(
              controller: screenshotController,
              child: Column(
                children: [
                  Text("Decreasing Timer : "),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      padding: const EdgeInsets.all(30.0),
                      decoration: BoxDecoration(
                        border:
                            Border.all(color: Colors.blueAccent, width: 5.0),
                        color: Colors.amberAccent,
                      ),
                      child: Text(_startTwo.toString())),
                  SizedBox(
                    height: 25,
                  ),
                  Text("Increasing Timer : "),
                  SizedBox(
                    height: 10,
                  ),
                  Container(
                      padding: const EdgeInsets.all(30.0),
                      decoration: BoxDecoration(
                        border:
                            Border.all(color: Colors.blueAccent, width: 5.0),
                        color: Colors.amberAccent,
                      ),
                      child: Text("$_start")),
                ],
              ),
            ),
            ElevatedButton(
              onPressed: () {
                increasingStartTimer();
                decreasingStartTimer();
              },
              child: Text("start"),
            ),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    _start = 0;
                    _startTwo = 61;
                  });
                },
                child: Text("Refresh")),
            ElevatedButton(
              child: Text(
                'Capture Above Widget',
              ),
              onPressed: () {
                screenshotController
                    .capture(delay: Duration(milliseconds: 10))
                    .then((capturedImage) async {
                  ShowCapturedWidget(context, capturedImage!);
                  _saved(capturedImage);
                }).catchError((onError) {
                  print(onError);
                });
              },
            ),
            ElevatedButton(
              child: Text(
                'Capture An Invisible Widget',
              ),
              onPressed: () {
                var container = Container(
                    padding: const EdgeInsets.all(30.0),
                    decoration: BoxDecoration(
                      border: Border.all(color: Colors.blueAccent,
                                         width: 5.0),
                      color: Colors.pink,
                    ),
                    child: Text(
                      "This is an invisible widget",
                      style: Theme.of(context).textTheme.headline6,
                    ));
 
                screenshotController
                    .captureFromWidget(
                        InheritedTheme.captureAll(
                            context, Material(child: container)),
                        delay: Duration(seconds: 1))
                    .then((capturedImage) {
                  ShowCapturedWidget(context, capturedImage);
                  _saved(capturedImage);
                });
              },
            ),
          ],
        ),
      ),
    );
  }
 
  Future<dynamic> ShowCapturedWidget(
      BuildContext context, Uint8List capturedImage) {
    return showDialog(
      useSafeArea: false,
      context: context,
      builder: (context) => Scaffold(
        appBar: AppBar(
          title: Text("Captured widget screenshot"),
        ),
        body: Center(
            child: capturedImage != null
                ? Image.memory(capturedImage)
                : Container()),
      ),
    );
  }
 
  _saved(image) async {
    final result = await ImageGallerySaver.saveImage(image);
    print("File Saved to Gallery");
  }
 
}


Output:



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads