simple_qr_gen 1.0.1 copy "simple_qr_gen: ^1.0.1" to clipboard
simple_qr_gen: ^1.0.1 copied to clipboard

A Flutter package for generating customizable QR codes with advanced styling options (colors, logos, shapes) and cross-platform share functionality.

example/lib/main.dart

import 'package:flex_color_picker/flex_color_picker.dart';
import 'package:flutter/material.dart';
import 'package:simple_qr_gen/simple_qr_gen.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Simple QR Gen Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFF6366F1),
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
        fontFamily: 'SF Pro Display',
      ),
      home: const QrGeneratorPage(),
    );
  }
}

class QrGeneratorPage extends StatefulWidget {
  const QrGeneratorPage({super.key});

  @override
  State<QrGeneratorPage> createState() => _QrGeneratorPageState();
}

class _QrGeneratorPageState extends State<QrGeneratorPage>
    with SingleTickerProviderStateMixin {
  final TextEditingController _textController = TextEditingController(
    text: 'https://flutter.dev',
  );

  Color _foregroundColor = const Color(0xFF1E1B4B);
  Color _backgroundColor = const Color(0xFFF8FAFC);
  QrShape _selectedShape = QrShape.rounded;
  final double _qrSize = 280;
  bool _isSharing = false;

  late AnimationController _animationController;
  late Animation<double> _scaleAnimation;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      duration: const Duration(milliseconds: 200),
      vsync: this,
    );
    _scaleAnimation = Tween<double>(begin: 1.0, end: 0.95).animate(
      CurvedAnimation(parent: _animationController, curve: Curves.easeInOut),
    );
  }

  @override
  void dispose() {
    _textController.dispose();
    _animationController.dispose();
    super.dispose();
  }

  Future<void> _shareQr() async {
    setState(() => _isSharing = true);
    _animationController.forward().then((_) => _animationController.reverse());

    final result = await QrSharer.share(
      data: _textController.text,
      size: 1024,
      style: QrStyle(
        foregroundColor: _foregroundColor,
        backgroundColor: _backgroundColor,
        shape: _selectedShape,
      ),
      fileName: 'qr_code_${DateTime.now().millisecondsSinceEpoch}',
      shareText: 'Check out this QR code!',
    );

    setState(() => _isSharing = false);

    if (mounted && !result.success) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Row(
            children: [
              const Icon(
                Icons.error,
                color: Colors.redAccent,
              ),
              const SizedBox(width: 12),
              Expanded(
                child: Text(
                  result.errorMessage ?? 'Failed to share QR code',
                ),
              ),
            ],
          ),
          behavior: SnackBarBehavior.floating,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
          backgroundColor: const Color(0xFF1E1B4B),
        ),
      );
    }
  }

  Future<void> _pickColor(bool isForeground) async {
    final currentColor = isForeground ? _foregroundColor : _backgroundColor;

    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(
          isForeground ? 'Pick Foreground Color' : 'Pick Background Color',
        ),
        content: SingleChildScrollView(
          child: ColorPicker(
            color: currentColor,
            onColorChanged: (color) {
              setState(() {
                if (isForeground) {
                  _foregroundColor = color;
                } else {
                  _backgroundColor = color;
                }
              });
            },
            pickersEnabled: const {
              ColorPickerType.wheel: true,
              ColorPickerType.accent: false,
              ColorPickerType.primary: false,
            },
            enableShadesSelection: true,
            width: 44,
            height: 44,
            borderRadius: 22,
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Done'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        decoration: const BoxDecoration(
          gradient: LinearGradient(
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
            colors: [
              Color(0xFF0F0E1A),
              Color(0xFF1E1B4B),
              Color(0xFF312E81),
            ],
          ),
        ),
        child: SafeArea(
          child: SingleChildScrollView(
            padding: const EdgeInsets.all(24),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                // Header
                const Text(
                  'Simple QR Gen',
                  style: TextStyle(
                    fontSize: 32,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                    letterSpacing: -0.5,
                  ),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 8),
                Text(
                  'Generate beautiful QR codes instantly',
                  style: TextStyle(
                    fontSize: 16,
                    color: Colors.white.withValues(alpha: 0.7),
                  ),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 40),

                // QR Preview Card
                Center(
                  child: AnimatedBuilder(
                    animation: _scaleAnimation,
                    builder: (context, child) => Transform.scale(
                      scale: _scaleAnimation.value,
                      child: child,
                    ),
                    child: Container(
                      padding: const EdgeInsets.all(24),
                      decoration: BoxDecoration(
                        color: _backgroundColor,
                        borderRadius: BorderRadius.circular(24),
                        boxShadow: [
                          BoxShadow(
                            color: _foregroundColor.withValues(alpha: 0.3),
                            blurRadius: 40,
                            offset: const Offset(0, 20),
                          ),
                        ],
                      ),
                      child: SimpleQrGen(
                        data: _textController.text.isEmpty
                            ? 'https://flutter.dev'
                            : _textController.text,
                        size: _qrSize,
                        style: QrStyle(
                          foregroundColor: _foregroundColor,
                          backgroundColor: _backgroundColor,
                          shape: _selectedShape,
                          logo: const AssetImage('assets/logo.png'),
                          errorCorrectionLevel: 2,
                        ),
                      ),
                    ),
                  ),
                ),
                const SizedBox(height: 40),

                // Input Section
                _buildGlassCard(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Content',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w600,
                          color: Colors.white70,
                          letterSpacing: 0.5,
                        ),
                      ),
                      const SizedBox(height: 12),
                      TextField(
                        controller: _textController,
                        onChanged: (_) => setState(() {}),
                        style: const TextStyle(color: Colors.white),
                        decoration: InputDecoration(
                          hintText: 'Enter text or URL...',
                          hintStyle: TextStyle(
                            color: Colors.white.withValues(alpha: 0.4),
                          ),
                          filled: true,
                          fillColor: Colors.white.withValues(alpha: 0.05),
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(12),
                            borderSide: BorderSide.none,
                          ),
                          prefixIcon: const Icon(
                            Icons.qr_code_2,
                            color: Colors.white54,
                          ),
                        ),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 20),

                // Style Section
                _buildGlassCard(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Style',
                        style: TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w600,
                          color: Colors.white70,
                          letterSpacing: 0.5,
                        ),
                      ),
                      const SizedBox(height: 16),

                      // Color pickers row
                      Row(
                        children: [
                          Expanded(
                            child: _buildColorButton(
                              label: 'Foreground',
                              color: _foregroundColor,
                              onTap: () => _pickColor(true),
                            ),
                          ),
                          const SizedBox(width: 16),
                          Expanded(
                            child: _buildColorButton(
                              label: 'Background',
                              color: _backgroundColor,
                              onTap: () => _pickColor(false),
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 20),

                      // Shape selector
                      const Text(
                        'Shape',
                        style: TextStyle(
                          fontSize: 12,
                          color: Colors.white54,
                        ),
                      ),
                      const SizedBox(height: 8),
                      Row(
                        children: QrShape.values.map((shape) {
                          final isSelected = shape == _selectedShape;
                          return Expanded(
                            child: GestureDetector(
                              onTap: () => setState(() => _selectedShape = shape),
                              child: AnimatedContainer(
                                duration: const Duration(milliseconds: 200),
                                margin: const EdgeInsets.symmetric(horizontal: 4),
                                padding: const EdgeInsets.symmetric(
                                  vertical: 12,
                                  horizontal: 8,
                                ),
                                decoration: BoxDecoration(
                                  color: isSelected
                                      ? const Color(0xFF6366F1)
                                      : Colors.white.withValues(alpha: 0.05),
                                  borderRadius: BorderRadius.circular(12),
                                  border: Border.all(
                                    color: isSelected
                                        ? const Color(0xFF6366F1)
                                        : Colors.white.withValues(alpha: 0.1),
                                  ),
                                ),
                                child: Column(
                                  children: [
                                    _buildShapeIcon(shape, isSelected),
                                    const SizedBox(height: 4),
                                    Text(
                                      shape.name[0].toUpperCase() +
                                          shape.name.substring(1),
                                      style: TextStyle(
                                        fontSize: 10,
                                        color: isSelected
                                            ? Colors.white
                                            : Colors.white54,
                                        fontWeight: isSelected
                                            ? FontWeight.w600
                                            : FontWeight.normal,
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                            ),
                          );
                        }).toList(),
                      ),
                    ],
                  ),
                ),
                const SizedBox(height: 32),

                // Share Button
                GestureDetector(
                  onTap: _isSharing ? null : _shareQr,
                  child: AnimatedContainer(
                    duration: const Duration(milliseconds: 200),
                    padding: const EdgeInsets.symmetric(vertical: 18),
                    decoration: BoxDecoration(
                      gradient: const LinearGradient(
                        colors: [Color(0xFF6366F1), Color(0xFF8B5CF6)],
                      ),
                      borderRadius: BorderRadius.circular(16),
                      boxShadow: [
                        BoxShadow(
                          color: const Color(0xFF6366F1).withValues(alpha: 0.4),
                          blurRadius: 20,
                          offset: const Offset(0, 10),
                        ),
                      ],
                    ),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        if (_isSharing)
                          const SizedBox(
                            width: 20,
                            height: 20,
                            child: CircularProgressIndicator(
                              strokeWidth: 2,
                              valueColor: AlwaysStoppedAnimation(Colors.white),
                            ),
                          )
                        else
                          const Icon(Icons.share_rounded, color: Colors.white),
                        const SizedBox(width: 12),
                        Text(
                          _isSharing ? 'Sharing...' : 'Share QR Code',
                          style: const TextStyle(
                            fontSize: 16,
                            fontWeight: FontWeight.w600,
                            color: Colors.white,
                            letterSpacing: 0.3,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
                const SizedBox(height: 24),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildGlassCard({required Widget child}) {
    return Container(
      padding: const EdgeInsets.all(20),
      decoration: BoxDecoration(
        color: Colors.white.withValues(alpha: 0.05),
        borderRadius: BorderRadius.circular(20),
        border: Border.all(
          color: Colors.white.withValues(alpha: 0.1),
        ),
      ),
      child: child,
    );
  }

  Widget _buildColorButton({
    required String label,
    required Color color,
    required VoidCallback onTap,
  }) {
    return GestureDetector(
      onTap: onTap,
      child: Container(
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: Colors.white.withValues(alpha: 0.05),
          borderRadius: BorderRadius.circular(12),
          border: Border.all(
            color: Colors.white.withValues(alpha: 0.1),
          ),
        ),
        child: Row(
          children: [
            Container(
              width: 32,
              height: 32,
              decoration: BoxDecoration(
                color: color,
                borderRadius: BorderRadius.circular(8),
                border: Border.all(
                  color: Colors.white.withValues(alpha: 0.2),
                  width: 2,
                ),
              ),
            ),
            const SizedBox(width: 12),
            Text(
              label,
              style: const TextStyle(
                fontSize: 12,
                color: Colors.white70,
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildShapeIcon(QrShape shape, bool isSelected) {
    final color = isSelected ? Colors.white : Colors.white54;
    const size = 20.0;

    switch (shape) {
      case QrShape.square:
        return Container(
          width: size,
          height: size,
          decoration: BoxDecoration(
            color: color,
          ),
        );
      case QrShape.rounded:
        return Container(
          width: size,
          height: size,
          decoration: BoxDecoration(
            color: color,
            borderRadius: BorderRadius.circular(4),
          ),
        );
      case QrShape.dots:
        return Container(
          width: size * 0.7,
          height: size * 0.7,
          decoration: BoxDecoration(
            color: color,
            shape: BoxShape.circle,
          ),
        );
      case QrShape.circle:
        return Container(
          width: size,
          height: size,
          decoration: BoxDecoration(
            color: color,
            shape: BoxShape.circle,
          ),
        );
    }
  }
}
3
likes
150
points
112
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package for generating customizable QR codes with advanced styling options (colors, logos, shapes) and cross-platform share functionality.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, path_provider, qr, share_plus

More

Packages that depend on simple_qr_gen