Screenshot and share widget

Ya'll know Chris Coffee's article(https://community.flutterflow.io/community-tutorials/post/flutter-flow-how-to-screenshot-any-widget-dbWT5hlhBUbQbnh) on how to screenshot a widget. I recently used his code and modified a little bit and added a share action on top of it. Thought I'd share it here. I made a short video: https://youtu.be/PWfZMJEezWA. Here is the code for the custom widget and action.

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/actions/index.dart'; // Imports other custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom action code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'dart:typed_data';
import 'package:share_plus/share_plus.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';

Future<void> shareScreenshot(FFUploadedFile imageBytes) async {
  try {
    if (imageBytes.bytes == null) {
      print('Error: imageBytes is null');
      return;
    }

    final Uint8List bytes = imageBytes.bytes!; // Ensure non-null

    // Save the file locally before sharing
    final tempDir = await getTemporaryDirectory();
    final filePath = '${tempDir.path}/${imageBytes.name ?? "screenshot.png"}';
    final file = File(filePath);
    await file.writeAsBytes(bytes);

    // Share the image
    await Share.shareXFiles([XFile(filePath)], text: "Check out this quote!");
  } catch (e) {
    print('Error sharing screenshot: $e');
  }
}

// Set your action name, define your arguments and return parameter,
// and then add the boilerplate code using the green button on the right!
// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/custom_code/actions/index.dart'; // Imports custom actions
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'index.dart'; // Imports other custom widgets

/* Add these to pubspec.yaml:
screenshot: ^2.1.0
*/
import 'package:screenshot/screenshot.dart';

class WidgetScreenshot extends StatefulWidget {
  const WidgetScreenshot({
    Key? key,
    this.width,
    this.height,
    required this.screenshotChild,
    this.onScreenshotCaptured,
  }) : super(key: key);

  final double? width;
  final double? height;
  final Widget Function()? screenshotChild;
  final Future Function(FFUploadedFile screenshot)? onScreenshotCaptured;

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

class _WidgetScreenshotState extends State<WidgetScreenshot> {
  final screenshotController = ScreenshotController();

  Future captureScreenshot() async {
    try {
      final Uint8List? capturedImage = await screenshotController.capture();

      if (capturedImage != null && widget.onScreenshotCaptured != null) {
        final timestamp = DateTime.now().millisecondsSinceEpoch;
        final screenshotFile = FFUploadedFile(
          name: 'screenshot_$timestamp.png',
          bytes: capturedImage,
        );

        await widget.onScreenshotCaptured!(screenshotFile);
      }
    } catch (e) {
      print('Error capturing screenshot: $e');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        // Screenshot Container
        Container(
          width: widget.width,
          height: widget.height,
          child: Screenshot(
            controller: screenshotController,
            child: widget.screenshotChild?.call() ?? Container(),
          ),
        ),
        // Share Button Positioned Inside an Align + Row
        Align(
          alignment: AlignmentDirectional(0, 1), // Bottom of the container
          child: Container(
            width: double.infinity,
            decoration: BoxDecoration(),
            child: Align(
              alignment: AlignmentDirectional(1, -1), // Top-right placement
              child: Padding(
                padding:
                    EdgeInsets.only(top: 192), // Moves the button down by 192px
                child: Row(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.end,
                  children: [
                    Container(
                      decoration: BoxDecoration(
                        color: FlutterFlowTheme.of(context)
                            .secondaryBackground, // Background color
                        borderRadius:
                            BorderRadius.circular(8), // Rounded corners
                      ),
                      child: IconButton(
                        icon: Icon(
                          Icons.near_me_rounded, // Replacing FaIcon correctly
                          color: FlutterFlowTheme.of(context)
                              .primaryText, // Icon color
                          size: 18, // Ensure the same size as FaIcon
                        ),
                        onPressed: captureScreenshot, // Captures the screenshot
                        iconSize: 24, // Ensures proper tap area
                      ),
                    ),
                  ],
                ),
              ),
            ),
          ),
        )
      ],
    );
  }
}
// Set your widget name, define your parameter, and then add the
// boilerplate code using the green button on the right!

https://youtube.com/shorts/f7bEUp9Tj4Q

3
4 replies