Flutter Convert Widget to Image

I get this question a lot if I am also a flutter developer and most recruiters ask me if I have equal proficiency in both, and most of the time my response to this is yes I do have equal proficiency in both and I am on the journey of adding more technologies to my stack as it relates to mobile application development.

To the subject how do you convert and widget to an image programmatically? Yes, many would go for the screenshot package in pub.dev. However, I am a great advocate of having lighter applications, and I love taking full control of what a feature does even if I am using a plugin, package or library. Now the aforementioned package is awesome and allows you to take screenshots and save them as an image, how about you want to convert your widget to another file format asides from PNG or JPEG?

Here I am going to show you how to convert your widget to any file format you wish and perhaps be able to share it in that format, provide you can save it to the device you work with.

Now flutter is a rendering framework, that mostly works on a rendering engine. See here for more, And we can utilize the rendering service to do so much provided we can render such a view. Firstly, let's mention an important setup on the view you want to convert and I must mention that you can convert whatsoever, remember everything is a widget in flutter. Oh boy! show me some code already :)

  1. import required services into your widget

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

  2. Create a Global key and create a nullable file(where we can save the file)
    ``GlobalKey _yourGlobalKey = GlobalKey();
    File? widgetFilePath;

  3. Wrap the widget you want to convert with the RepaintBoundary
    ``RepaintBoundary(
    key: _globalKey,
    child: Container()``
    Replace the container widget with any other of your choice

  4. Create the capture function that captures the wrapped widget through _yourGlobalkey you created.

    `Future<ui.Image> captureWidgetImage() async {
    RenderRepaintBoundary boundary =_globalKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
    final image = await boundary.toImage(pixelRatio: 1.0);

    return image;
    }

  5. Now we have the set-up complete and create the function how can we call the `captureWidgetImage` function.

  6. Now we can actually just capture the widget but what can we do with it ? how about we save the image :)
    Future<void> saveImageAsPng() async {

    /// TODO Check File write permission
    /// you can change the format here to pdf,jpeg etc

    //1 widgetFilePath = File(appDocDirectory.path + '/capturedWidget.png');

    //2
    if(mounted){

    //3 ui.Image image = await captureImage();

    //4 ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    //5 if (byteData != null) {

    //6 final buffer = byteData.buffer.asUint8List();

    //7 await widgetFilePath?.writeAsBytes(buffer);
    }

    }

  7. Using the save saveImageAsPng and captureWidgetImage
    You can use these functions by calling saveImageAsPng() in say a button click when you do this
    i. A widgetFilePath file u created initially is then initialized and assigned a path and a name.
    ii. In #2 You check if the widget is still in the tree and not disposed you initialise ui.Image and call the captureImage in #3 Remember it returns an image.

    iii. since better work on images as bytes data in #4 we convert the to bytes with toByteData and format it into png format
    iv. In #5 we check we actually have an image and then in #6 we convert these bytes to a usable list asUint8List and write the parts of this list to the file we created initially.

    Thats it....!
    Where to go next!!!!
    You can share images and save them in your gallery or show users in a pop, a very good use case is to show or share qr images, show or share receipts etc. Here is a GitHub gist of more code 👨‍💻

    Thanks for reading this far, until next time, happy hacking👨‍💻 !!!