qr_scanner_hybrid 0.1.0+1 copy "qr_scanner_hybrid: ^0.1.0+1" to clipboard
qr_scanner_hybrid: ^0.1.0+1 copied to clipboard

High-accuracy QR code scanner using dual scanning engines (Google ML Kit + ZXing) for maximum reliability in various lighting conditions.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:qr_scanner_hybrid/qr_scanner_hybrid.dart';

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

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

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

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  String? _lastScannedCode;
  String? _lastEngine;
  final List<Map<String, String>> _scanHistory = [];

  // Example 1: With callback and auto-close
  void _scanWithAutoClose() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => QrScannerHybrid(
          autoClose: true,
          onDetected: (data, engine) {
            print('Detected: $data via $engine');
          },
          config: const ScannerConfig(
            title: 'Scan QR Code',
            borderColor: Colors.blue,
            scanAreaSize: 0.75,
          ),
        ),
      ),
    );

    if (result != null && result is Map<String, String>) {
      _addToHistory(result['data']!, result['engine']!);
    }
  }

  // Example 2: With custom UI config
  void _scanWithCustomUI() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => QrScannerHybrid(
          onDetected: (data, engine) {
            _showSnackBar('Scanned: ${data.substring(0, 20)}...');
          },
          config: const ScannerConfig(
            title: 'Custom Scanner',
            borderColor: Colors.purple,
            borderWidth: 4,
            borderRadius: 20,
            scanAreaSize: 0.65,
            appBarColor: Colors.purple,
            overlayColor: Colors.black45,
          ),
        ),
      ),
    );

    if (result != null && result is Map<String, String>) {
      _addToHistory(result['data']!, result['engine']!);
    }
  }

  // Example 3: Minimal UI
  void _scanMinimal() async {
    final result = await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => QrScannerHybrid(
          autoClose: true,
          config: const ScannerConfig(
            showAppBar: true,
            showStatusText: false,
            borderColor: Colors.green,
            scanAreaSize: 0.8,
          ),
        ),
      ),
    );

    if (result != null && result is Map<String, String>) {
      _addToHistory(result['data']!, result['engine']!);
    }
  }

  // Example 4: With onClose callback
  void _scanWithCloseCallback() async {
    await Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => QrScannerHybrid(
          onDetected: (data, engine) {
            _addToHistory(data, engine);
          },
          onClose: () {
            print('Scanner closed');
          },
          config: const ScannerConfig(
            title: 'Scan & Track',
            borderColor: Colors.orange,
          ),
        ),
      ),
    );
  }

  void _addToHistory(String data, String engine) {
    setState(() {
      _lastScannedCode = data;
      _lastEngine = engine;
      _scanHistory.insert(0, {'data': data, 'engine': engine});
      if (_scanHistory.length > 10) {
        _scanHistory.removeLast();
      }
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('QR Scanner Hybrid Example'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Header
            const Icon(
              Icons.qr_code_scanner,
              size: 80,
              color: Colors.blue,
            ),
            const SizedBox(height: 16),
            const Text(
              'High Accuracy QR Scanner',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 8),
            const Text(
              'Dual engine scanning with ML Kit + ZXing',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: 14,
                color: Colors.grey,
              ),
            ),
            const SizedBox(height: 32),

            // Scan Options
            const Text(
              'Scan Examples:',
              style: TextStyle(
                fontSize: 18,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 12),

            ElevatedButton.icon(
              onPressed: _scanWithAutoClose,
              icon: const Icon(Icons.flash_auto),
              label: const Text('Auto-Close Scanner'),
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.all(16),
                backgroundColor: Colors.blue,
                foregroundColor: Colors.white,
              ),
            ),
            const SizedBox(height: 8),

            ElevatedButton.icon(
              onPressed: _scanWithCustomUI,
              icon: const Icon(Icons.palette),
              label: const Text('Custom UI Colors'),
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.all(16),
                backgroundColor: Colors.purple,
                foregroundColor: Colors.white,
              ),
            ),
            const SizedBox(height: 8),

            ElevatedButton.icon(
              onPressed: _scanMinimal,
              icon: const Icon(Icons.minimize),
              label: const Text('Minimal UI'),
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.all(16),
                backgroundColor: Colors.green,
                foregroundColor: Colors.white,
              ),
            ),
            const SizedBox(height: 8),

            ElevatedButton.icon(
              onPressed: _scanWithCloseCallback,
              icon: const Icon(Icons.track_changes),
              label: const Text('With Callbacks'),
              style: ElevatedButton.styleFrom(
                padding: const EdgeInsets.all(16),
                backgroundColor: Colors.orange,
                foregroundColor: Colors.white,
              ),
            ),
            const SizedBox(height: 32),

            // Last Scan Result
            if (_lastScannedCode != null) ...[
              const Text(
                'Last Scan:',
                style: TextStyle(
                  fontSize: 18,
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 12),
              Container(
                padding: const EdgeInsets.all(16),
                decoration: BoxDecoration(
                  color: Colors.green.shade50,
                  borderRadius: BorderRadius.circular(12),
                  border: Border.all(color: Colors.green.shade200),
                ),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        const Icon(Icons.check_circle,
                            color: Colors.green, size: 20),
                        const SizedBox(width: 8),
                        Text(
                          'Detected via $_lastEngine',
                          style: const TextStyle(
                            fontWeight: FontWeight.bold,
                            color: Colors.green,
                          ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 12),
                    SelectableText(
                      _lastScannedCode!,
                      style: const TextStyle(
                        fontSize: 14,
                        fontFamily: 'monospace',
                      ),
                    ),
                  ],
                ),
              ),
              const SizedBox(height: 24),
            ],

            // Scan History
            if (_scanHistory.isNotEmpty) ...[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  const Text(
                    'Scan History:',
                    style: TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  TextButton(
                    onPressed: () {
                      setState(() {
                        _scanHistory.clear();
                        _lastScannedCode = null;
                        _lastEngine = null;
                      });
                    },
                    child: const Text('Clear'),
                  ),
                ],
              ),
              const SizedBox(height: 8),
              ListView.builder(
                shrinkWrap: true,
                physics: const NeverScrollableScrollPhysics(),
                itemCount: _scanHistory.length,
                itemBuilder: (context, index) {
                  final scan = _scanHistory[index];
                  return Card(
                    margin: const EdgeInsets.only(bottom: 8),
                    child: ListTile(
                      leading: CircleAvatar(
                        child: Text('${index + 1}'),
                      ),
                      title: Text(
                        scan['data']!.length > 50
                            ? '${scan['data']!.substring(0, 50)}...'
                            : scan['data']!,
                        style: const TextStyle(fontSize: 12),
                      ),
                      subtitle: Text(
                        'via ${scan['engine']}',
                        style: const TextStyle(fontSize: 11),
                      ),
                    ),
                  );
                },
              ),
            ],
          ],
        ),
      ),
    );
  }
}
1
likes
140
points
198
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

High-accuracy QR code scanner using dual scanning engines (Google ML Kit + ZXing) for maximum reliability in various lighting conditions.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

camera, flutter, flutter_zxing, google_mlkit_barcode_scanning, image, path_provider

More

Packages that depend on qr_scanner_hybrid