flutter_sticker_maker 0.1.0 copy "flutter_sticker_maker: ^0.1.0" to clipboard
flutter_sticker_maker: ^0.1.0 copied to clipboard

Flutter plugin to create stickers from images using iOS Vision/CoreImage and Android MLKit.

example/lib/main.dart

import 'dart:io'; // Added for Platform
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_sticker_maker/flutter_sticker_maker.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart'; // Added

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Sticker Maker Example',
      home: const StickerPage(),
    );
  }
}

class StickerPage extends StatefulWidget {
  const StickerPage({super.key});
  @override
  State<StickerPage> createState() => _StickerPageState();
}

class _StickerPageState extends State<StickerPage> {
  Uint8List? _inputImage;
  Uint8List? _stickerImage;
  bool _addBorder = true;
  String _borderColor = '#FFFFFF';
  double _borderWidth = 12.0;

  Future<bool> _requestPermissions({bool forCamera = false}) async {
    Map<Permission, PermissionStatus> statuses;
    List<Permission> permsToRequest = [Permission.photos];
    if (forCamera) {
      permsToRequest.add(Permission.camera);
    }

    statuses = await permsToRequest.request();

    bool allGranted = true;
    statuses.forEach((permission, status) {
      if (!(status.isGranted || (Platform.isIOS && status.isLimited))) {
        allGranted = false;
      }
    });
    return allGranted;
  }

  Future<void> _handlePermanentlyDenied({bool forCamera = false}) async {
    bool photosPermanentlyDenied = await Permission.photos.isPermanentlyDenied;
    bool cameraPermanentlyDenied =
        forCamera ? await Permission.camera.isPermanentlyDenied : false;

    if (photosPermanentlyDenied || (forCamera && cameraPermanentlyDenied)) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: const Text(
              'Permissions are permanently denied. Please enable them in app settings.',
            ),
            action: SnackBarAction(
              label: 'Settings',
              onPressed: () async {
                await openAppSettings();
              },
            ),
          ),
        );
      }
    }
  }

  Future<void> _pickImageFromGallery() async {
    final granted = await _requestPermissions(forCamera: false);
    if (!granted) {
      await _handlePermanentlyDenied(forCamera: false);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Photo library permission needed to pick images.'),
          ),
        );
      }
      return;
    }

    final picker = ImagePicker();
    final XFile? imageFile = await picker.pickImage(
      source: ImageSource.gallery,
    );
    if (imageFile != null) {
      final bytes = await imageFile.readAsBytes();
      setState(() {
        _inputImage = bytes;
        _stickerImage = null;
      });
    }
  }

  Future<void> _captureImageWithCamera() async {
    final granted = await _requestPermissions(forCamera: true);
    if (!granted) {
      await _handlePermanentlyDenied(forCamera: true);
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Camera and Photo library permissions needed.'),
          ),
        );
      }
      return;
    }

    final picker = ImagePicker();
    final XFile? imageFile = await picker.pickImage(source: ImageSource.camera);
    if (imageFile != null) {
      final bytes = await imageFile.readAsBytes();
      setState(() {
        _inputImage = bytes;
        _stickerImage = null;
      });
    }
  }

  Future<void> _createSticker() async {
    if (_inputImage == null) {
      ScaffoldMessenger.of(context).showSnackBar(
        const SnackBar(content: Text('Please select an image first.')),
      );
      return;
    }
    try {
      setState(() {
        _stickerImage = null; // Show loading or clear previous
      });
      final Uint8List? stickerBytes = await FlutterStickerMaker.makeSticker(
        _inputImage!,
        borderColor: _borderColor,
        addBorder: _addBorder,
        borderWidth: _borderWidth,
      );
      setState(() {
        _stickerImage = stickerBytes;
      });
      if (stickerBytes == null && mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Failed to create sticker. No result.')),
        );
      }
    } catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Failed to create sticker: $e')));
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey[400],
      appBar: AppBar(title: const Text('Sticker Maker Demo')),
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              // Action buttons
              ElevatedButton(
                onPressed: _pickImageFromGallery,
                child: const Text('Pick Image from Gallery'),
              ),
              ElevatedButton(
                onPressed: _captureImageWithCamera,
                child: const Text('Capture Image with Camera'),
              ),
              const SizedBox(height: 20),

              // Border controls
              if (_inputImage != null) ...[
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    const Text('Add Border:'),
                    Switch(
                      value: _addBorder,
                      onChanged: (value) {
                        setState(() {
                          _addBorder = value;
                        });
                      },
                    ),
                  ],
                ),
                if (_addBorder) ...[
                  const Text('Border Color:'),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      _buildColorButton('#FFFFFF', 'White'),
                      _buildColorButton('#FF0000', 'Red'),
                      _buildColorButton('#00FF00', 'Green'),
                      _buildColorButton('#0000FF', 'Blue'),
                      _buildColorButton('#FFFF00', 'Yellow'),
                    ],
                  ),
                  const SizedBox(height: 10),
                  Padding(
                    padding: const EdgeInsets.symmetric(horizontal: 20),
                    child: Column(
                      children: [
                        Text('Border Width: ${_borderWidth.round()}'),
                        Slider(
                          value: _borderWidth,
                          min: 2.0,
                          max: 30.0,
                          divisions: 28,
                          onChanged: (value) {
                            setState(() {
                              _borderWidth = value;
                            });
                          },
                        ),
                      ],
                    ),
                  ),
                ],
                const SizedBox(height: 10),
                ElevatedButton(
                  onPressed: _createSticker,
                  child: const Text('Create Sticker'),
                ),
              ],

              // Responsive image layout
              if (_inputImage != null || _stickerImage != null)
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: LayoutBuilder(
                    builder: (context, constraints) {
                      final isLargeScreen = constraints.maxWidth > 600;

                      if (isLargeScreen) {
                        // Horizontal layout for large screens
                        return Row(
                          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            if (_inputImage != null)
                              Expanded(
                                child: Column(
                                  children: [
                                    const Text(
                                      'Input Image:',
                                      style: TextStyle(
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                    const SizedBox(height: 8),
                                    Container(
                                      constraints: const BoxConstraints(
                                        maxHeight: 300,
                                      ),
                                      child: Image.memory(
                                        _inputImage!,
                                        fit: BoxFit.contain,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            if (_inputImage != null && _stickerImage != null)
                              const SizedBox(width: 20),
                            if (_stickerImage != null)
                              Expanded(
                                child: Column(
                                  children: [
                                    const Text(
                                      'Sticker Result:',
                                      style: TextStyle(
                                        fontWeight: FontWeight.bold,
                                      ),
                                    ),
                                    const SizedBox(height: 8),
                                    Container(
                                      constraints: const BoxConstraints(
                                        maxHeight: 300,
                                      ),
                                      child: Image.memory(
                                        _stickerImage!,
                                        fit: BoxFit.contain,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                          ],
                        );
                      } else {
                        // Vertical layout for small screens
                        return Column(
                          children: [
                            if (_inputImage != null) ...[
                              const Text(
                                'Input Image:',
                                style: TextStyle(fontWeight: FontWeight.bold),
                              ),
                              const SizedBox(height: 8),
                              Image.memory(_inputImage!, height: 200),
                              const SizedBox(height: 20),
                            ],
                            if (_stickerImage != null) ...[
                              const Text(
                                'Sticker Result:',
                                style: TextStyle(fontWeight: FontWeight.bold),
                              ),
                              const SizedBox(height: 8),
                              Image.memory(_stickerImage!, height: 200),
                            ],
                          ],
                        );
                      }
                    },
                  ),
                ),
            ],
          ),
        ),
      ),
    );
  }

  Widget _buildColorButton(String color, String label) {
    return GestureDetector(
      onTap: () {
        setState(() {
          _borderColor = color;
        });
      },
      child: Container(
        margin: const EdgeInsets.symmetric(horizontal: 4),
        padding: const EdgeInsets.all(8),
        decoration: BoxDecoration(
          color: Color(int.parse(color.substring(1), radix: 16) + 0xFF000000),
          border: Border.all(
            color: _borderColor == color ? Colors.black : Colors.grey,
            width: _borderColor == color ? 3 : 1,
          ),
          borderRadius: BorderRadius.circular(4),
        ),
        child: Text(
          label,
          style: TextStyle(
            color:
                color == '#FFFFFF' || color == '#FFFF00'
                    ? Colors.black
                    : Colors.white,
            fontSize: 12,
          ),
        ),
      ),
    );
  }
}
8
likes
0
points
48
downloads

Publisher

unverified uploader

Weekly Downloads

Flutter plugin to create stickers from images using iOS Vision/CoreImage and Android MLKit.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter

More

Packages that depend on flutter_sticker_maker

Packages that implement flutter_sticker_maker