super_qr_code_scanner 1.0.5 copy "super_qr_code_scanner: ^1.0.5" to clipboard
super_qr_code_scanner: ^1.0.5 copied to clipboard

A robust Flutter plugin for scanning QR codes from images using OpenCV and ZXing. High-performance native implementation with multi-platform support.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:super_qr_code_scanner/super_qr_code_scanner.dart';
import 'package:image_picker/image_picker.dart';
import 'package:super_qr_code_scanner_example/mixin/state_mixin.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Super QR Code Scanner Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const QRScannerDemo(),
    );
  }
}

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

  @override
  State<QRScannerDemo> createState() => _QRScannerDemoState();
}

class _QRScannerDemoState extends State<QRScannerDemo>
    with SafeStateMixin<QRScannerDemo> {
  final scanner = SuperQRCodeScanner();
  final imagePicker = ImagePicker();
  List<QRCode> results = [];
  bool isScanning = false;
  String? errorMessage;
  String selectedConfig = 'Default';

  @override
  void initState() {
    super.initState();
    scanner.updateConfig(QRScannerConfig.defaultConfig);
  }

  void _updateConfig(String config) {
    safeSetState(() {
      selectedConfig = config;
    });

    switch (config) {
      case 'Fast':
        scanner.updateConfig(QRScannerConfig.fastConfig);
        break;
      case 'Accurate':
        scanner.updateConfig(QRScannerConfig.accurateConfig);
        break;
      default:
        scanner.updateConfig(QRScannerConfig.defaultConfig);
    }

    _showSnackBar('Configuration changed to $config');
  }

  Future<void> _scanFromGallery() async {
    await _scanImage(ImageSource.gallery);
  }

  Future<void> _scanFromCamera() async {
    await _scanImage(ImageSource.camera);
  }

  Future<void> _scanImage(ImageSource source) async {
    try {
      // Pick image from gallery or camera
      final XFile? pickedFile = await imagePicker.pickImage(
        source: source,
        maxWidth: 1920,
        maxHeight: 1920,
      );

      if (!mounted) return;

      safeSetState(() {
        isScanning = true;
        errorMessage = null;
        results = [];
      });

      if (pickedFile == null) {
        safeSetState(() {
          isScanning = false;
        });
        _showSnackBar('No image selected');
        return;
      }

      // Run scan in background to avoid blocking UI
      final qrCodes = await scanner.scanImageFile(pickedFile.path);

      safeSetState(() {
        results = qrCodes;
        isScanning = false;
      });

      if (qrCodes.isEmpty) {
        _showSnackBar('No QR codes found in image');
      } else {
        _showSnackBar('Found ${qrCodes.length} QR code(s)');
      }
    } on InvalidParameterException catch (e) {
      safeSetState(() {
        isScanning = false;
        errorMessage = 'Invalid input: ${e.message}';
      });
      _showSnackBar(errorMessage!);
    } on ImageProcessingException catch (e) {
      safeSetState(() {
        isScanning = false;
        errorMessage = 'Processing failed: ${e.message}';
      });
      _showSnackBar(errorMessage!);
    } catch (e) {
      safeSetState(() {
        isScanning = false;
        errorMessage = 'Error: $e';
      });
      _showSnackBar(errorMessage!);
    }
  }

  void _showSnackBar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text(message)),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: const Text('Super QR Code Scanner'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Configuration selector
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Configuration',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      const SizedBox(height: 12),
                      SegmentedButton<String>(
                        segments: const [
                          ButtonSegment(
                            value: 'Fast',
                            label: Text('Fast'),
                            icon: Icon(Icons.speed),
                          ),
                          ButtonSegment(
                            value: 'Default',
                            label: Text('Default'),
                            icon: Icon(Icons.balance),
                          ),
                          ButtonSegment(
                            value: 'Accurate',
                            label: Text('Accurate'),
                            icon: Icon(Icons.high_quality),
                          ),
                        ],
                        selected: {selectedConfig},
                        onSelectionChanged: (Set<String> selection) {
                          _updateConfig(selection.first);
                        },
                      ),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 16),
              // Scan buttons
              Row(
                children: [
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: isScanning ? null : _scanFromGallery,
                      icon: isScanning
                          ? const SizedBox(
                              width: 20,
                              height: 20,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.photo_library),
                      label: const Text('Gallery'),
                      style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.all(16),
                      ),
                    ),
                  ),
                  const SizedBox(width: 12),
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: isScanning ? null : _scanFromCamera,
                      icon: const Icon(Icons.camera_alt),
                      label: const Text('Camera'),
                      style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.all(16),
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 24),
              // Results section
              if (results.isNotEmpty) ...[
                const Text(
                  'Results:',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 8),
                ListView.builder(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  itemCount: results.length,
                  itemBuilder: (context, index) {
                    final qr = results[index];
                    return Card(
                      child: ListTile(
                        leading: CircleAvatar(
                          child: Text('${index + 1}'),
                        ),
                        title: Text(
                          qr.content,
                          maxLines: 2,
                          overflow: TextOverflow.ellipsis,
                        ),
                        subtitle: Text('Format: ${qr.format}'),
                        trailing: IconButton(
                          icon: const Icon(Icons.copy),
                          onPressed: () {
                            // In a real app, copy to clipboard
                            _showSnackBar('Copied: ${qr.content}');
                          },
                        ),
                      ),
                    );
                  },
                ),
              ] else if (errorMessage != null)
                Card(
                  color: Colors.red.shade50,
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Row(
                      children: [
                        const Icon(Icons.error_outline, color: Colors.red),
                        const SizedBox(width: 12),
                        Expanded(
                          child: Text(
                            errorMessage!,
                            style: const TextStyle(color: Colors.red),
                          ),
                        ),
                      ],
                    ),
                  ),
                )
              else
                const SizedBox(
                  height: 200,
                  child: Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        Icon(
                          Icons.qr_code_2,
                          size: 64,
                          color: Colors.grey,
                        ),
                        SizedBox(height: 16),
                        Text(
                          'No results yet',
                          style: TextStyle(
                            fontSize: 16,
                            color: Colors.grey,
                          ),
                        ),
                        SizedBox(height: 8),
                        Text(
                          'Scan an image to see QR codes',
                          style: TextStyle(
                            fontSize: 14,
                            color: Colors.grey,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              const SizedBox(height: 24),
              // Usage information
              const Card(
                child: Padding(
                  padding: EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        children: [
                          Icon(Icons.info_outline, color: Colors.blue),
                          SizedBox(width: 8),
                          Text(
                            'How to use',
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      SizedBox(height: 12),
                      Text(
                        '1. Tap "Gallery" to select an image\n'
                        '   or "Camera" to take a photo\n\n'
                        '2. The app will scan for QR codes\n\n'
                        '3. Results will appear below\n\n'
                        'Tip: Try different configurations\n'
                        'for varying quality images',
                        style: TextStyle(fontSize: 14),
                      ),
                    ],
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
1
likes
160
points
0
downloads

Publisher

unverified uploader

Weekly Downloads

A robust Flutter plugin for scanning QR codes from images using OpenCV and ZXing. High-performance native implementation with multi-platform support.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

archive, args, ffi, flutter, http, path

More

Packages that depend on super_qr_code_scanner

Packages that implement super_qr_code_scanner