How to Capture Widgets as Images in Flutter

Aug 28, 2021 | Programming

Have you ever found yourself wanting to capture not just the visible parts of your Flutter widgets, but even the ones that aren’t rendered on the screen? Look no further! With a simple package, you can easily create image snapshots of your widgets. This guide will walk you through the process of setting up and using this package effectively, with some troubleshooting tips along the way.

Getting Started

Follow these steps to begin capturing widgets in your Flutter application.

1. Create an Instance of Screenshot Controller

First, let’s initialize our screenshot controller. This will help manage the capturing of your widgets.

dart
class _MyHomePageState extends State {
  int _counter = 0;
  Uint8List _imageFile;

  // Create an instance of ScreenshotController
  ScreenshotController screenshotController = ScreenshotController();

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }
}

2. Wrap Your Widget Inside a Screenshot Widget

Next, you need to wrap the widget you wish to capture inside the Screenshot widget. Assign the previously created controller to it.

dart
Screenshot(
  controller: screenshotController,
  child: Text("This text will be captured as image"),
),

3. Capture the Screenshot

To capture the screenshot, simply call the capture method. This returns a Uint8List, which you’ll then store for further uses.

dart
screenshotController.capture().then((Uint8List image) {
  // Capture Done
  setState(() {
    _imageFile = image;
  });
}).catchError((onError) {
  print(onError);
});

Capturing Widgets That Are Not Part of the Widget Tree

For capturing invisible widgets (like those not rendered yet), you can use the captureFromWidget method. Let’s see how to do that:

dart
screenshotController.captureFromWidget(
  Container(
    padding: const EdgeInsets.all(30.0),
    decoration: BoxDecoration(
      border: Border.all(color: Colors.blueAccent, width: 5.0),
      color: Colors.redAccent,
    ),
    child: Text("This is an invisible widget"),
  )
).then((capturedImage) {
  // Handle captured image
});

Understanding the Concept Through an Analogy

Imagine you’d like to capture a beautiful painting behind a curtain (an invisible widget). By pulling back the curtain (using captureFromWidget), you reveal the artwork and take a picture of it. Similarly, the screenshot package allows you to access and capture those components that aren’t immediately visible on your screen, providing a comprehensive snapshot of your app’s visual state.

Capturing Long Widgets

If you have a long widget, like a list, use the captureFromLongWidget function.

dart
var randomItemCount = Random().nextInt(100);
var myLongWidget = Builder(builder: (context) {
  return Container(
    padding: const EdgeInsets.all(30.0),
    decoration: BoxDecoration(
      border: Border.all(color: Colors.blueAccent, width: 5.0),
      color: Colors.redAccent,
    ),
    child: Column(
      mainAxisSize: MainAxisSize.min,
      children: [
        for (int i = 0; i < randomItemCount; i++)
          Text("Tile Index $i"),
      ],
    ),
  );
});

// Use captureFromLongWidget to take the screenshot
screenshotController.captureFromLongWidget(
  InheritedTheme.captureAll(
    context,
    Material(
      child: myLongWidget,
    ),
  ),
  delay: Duration(milliseconds: 100),
  context: context,
  constraints: BoxConstraints(
    maxHeight: 1000,
    maxWidth: 1000,
  ),
).then((capturedImage) {
  // Handle captured image
});

Saving Images

You can save the captured images to specific locations or directly to the gallery. Use the captureAndSave method to specify a directory location:

dart
final directory = (await getApplicationDocumentsDirectory()).path;
String fileName = DateTime.now().microsecondsSinceEpoch.toString();
screenshotController.captureAndSave(
  path: directory,
  fileName: fileName,
);

Troubleshooting

Here are some common troubleshooting tips if you encounter issues:

  • Issue: Captured image appears pixelated.
    Solution: Adjust the pixelRatio. This parameter scales logical pixels relative to output image size.
  • Issue: Images do not render properly if they're not rasterized in time.
    Solution: Insert a small delay before capturing the screenshot like so: screenshotController.capture(delay: Duration(milliseconds: 10))

For more insights, updates, or to collaborate on AI development projects, stay connected with fxis.ai.

Known Issues

  • Platform views are not supported (for example, Google Maps or Camera).

At fxis.ai, we believe that such advancements are crucial for the future of AI, as they enable more comprehensive and effective solutions. Our team is continually exploring new methodologies to push the envelope in artificial intelligence, ensuring that our clients benefit from the latest technological innovations.

Stay Informed with the Newest F(x) Insights and Blogs

Tech News and Blog Highlights, Straight to Your Inbox