Shashi Techlogues

Flutter: How to take Screenshot of the screen or widget and save as image

In this post, we will discuss how to take a screenshot of a widget and save it as an image. Let's take a use case where we need this functionality.

Here is an app to read quotes in a beautiful background.

Flutter quote app
Quote App

The basic structure of the app looks something like this:

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

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

class _MyHomePageState extends State<MyHomePage> {
  List<Quote> _quotes = [
    Quote(
      content: "Friendship is Love without his wings!",
      author: "Lord Byron",
      image: 'quote-1.jpeg'
    )
  ];

  String _currentImage = 'assets/img/image1.jpeg';

  initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Container(
            decoration: BoxDecoration(
              image: DecorationImage(
                image: AssetImage('assets/img/placeholder.jpeg'),
                fit: BoxFit.cover,
              ),
            ),
          ),
          PageView.builder(
            scrollDirection: Axis.vertical,
            itemCount: _quotes.length,
            itemBuilder: (context, position) {
              return Container(
                width: double.infinity,
                child: Column(
                  children: <Widget>[
                    Expanded(
                      child: Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        crossAxisAlignment: CrossAxisAlignment.center,
                        children: <Widget>[
                          Padding(
                            padding: new EdgeInsets.all(25.0),
                            child: Text(
                              _quotes[position].content,
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 24.0,
                                fontWeight: FontWeight.bold
                              ),
                            ),
                          ),
                          Padding(
                            padding: new EdgeInsets.all(25.0),
                            child: Text(
                              '- ' + _quotes[position].author,
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                color: Colors.white,
                                fontSize: 16.0,
                                fontWeight: FontWeight.bold,
                                fontStyle: FontStyle.italic
                              ),
                            ),
                          ),
                        ],
                      ),
                    ),
                  ],
                ),
              );
            },
          ),
        ],
      ),
    );
  }
}

Users might want to share the quote with friends and family. So adding a download button will allow them to take a screenshot of the screen and save it on their mobile device.

Let's add a save/download button.

Quote app with download button

So we have added a button that should take the screenshot and save it as an image.

Here is the code for adding the download button:

Positioned(
  right: 15.0,
  bottom: 12.0,
  child: InkWell(
    onTap: () {
      download();
    },
    child: Icon(
      Icons.download_sharp,
      color: Colors.white70
    ),
  ),
),

On clicking the download button, the onTap function will call the download() function.

Prepare and Download the Image

We will use the RepaintBoundary Flutter class to achieve this.

Wrap the widgets you want to take a screenshot of inside RepaintBoundary.

RepaintBoundary needs to be specified with a GlobalKey, so let's set that.

static GlobalKey _globalKey = GlobalKey();

Finally, we need to convert the RepaintBoundary widget into an image. Remember the download() function that we defined for the download button click.

Let's add the magic in that function.

Future<Null> download() async {
  RenderRepaintBoundary boundary =
      _globalKey.currentContext.findRenderObject();

  ui.Image image = await boundary.toImage();

  final directory = (await getExternalStorageDirectory()).path;

  ByteData byteData =
      await image.toByteData(format: ui.ImageByteFormat.png);

  Uint8List pngBytes = byteData.buffer.asUint8List();

  final now = new DateTime.now();

  File imgFile = new File('$directory/Sher_$now.png');

  imgFile.writeAsBytes(pngBytes);

  Toast.show(
    'Saved to $directory',
    context,
    duration: Toast.LENGTH_SHORT,
    gravity: Toast.BOTTOM
  );
}

This function converts the widget into an image and stores the resulting byte data as an image in the device storage.


Thanks for reading. If you have some feedback, please reach out to me on Twitter or GitHub .