qr_barcode_dialog_scanner 1.0.0 copy "qr_barcode_dialog_scanner: ^1.0.0" to clipboard
qr_barcode_dialog_scanner: ^1.0.0 copied to clipboard

A Flutter package for scanning QR codes and barcodes using a dialog.

example/lib/main.dart

// example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:qr_barcode_scanner/qr_barcode_scanner.dart';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'QR Barcode Scanner Examples',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ExamplesHomePage(),
    );
  }
}

class ExamplesHomePage extends StatefulWidget {
  @override
  _ExamplesHomePageState createState() => _ExamplesHomePageState();
}

class _ExamplesHomePageState extends State<ExamplesHomePage> {
  List<ScannerResult> scanHistory = [];
  bool isPermissionGranted = false;

  @override
  void initState() {
    super.initState();
    _checkPermissions();
  }

  // Example 1: Check Camera Permission
  Future<void> _checkPermissions() async {
    final granted = await QRBarcodeScanner.isCameraPermissionGranted();
    setState(() {
      isPermissionGranted = granted;
    });
    print('Camera permission granted: $granted');
  }

  // Example 2: Request Camera Permission
  Future<void> _requestPermission() async {
    final granted = await QRBarcodeScanner.requestCameraPermission();
    setState(() {
      isPermissionGranted = granted;
    });
    
    if (granted) {
      _showSnackBar('Camera permission granted!', Colors.green);
    } else {
      _showSnackBar('Camera permission denied!', Colors.red);
    }
  }

  // Example 3: Basic Scanner Dialog
  Future<void> _basicScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    try {
      final result = await QRBarcodeScanner.showScannerDialog(context);
      
      if (result != null) {
        _addToHistory(result);
        _showResultDialog('Basic Scan Result', result);
      } else {
        _showSnackBar('Scan cancelled', Colors.orange);
      }
    } catch (e) {
      _showSnackBar('Error: $e', Colors.red);
    }
  }

  // Example 4: Custom Styled Scanner
  Future<void> _customStyledScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '🎨 Custom Scanner',
      subtitle: 'Beautifully styled scanner',
      primaryColor: Colors.purple,
      backgroundColor: Colors.black87,
      allowFlashToggle: true,
      allowCameraToggle: true,
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Custom Styled Scan', result);
    }
  }

  // Example 5: Scanner with Timeout
  Future<void> _scanWithTimeout() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '⏱️ Timed Scanner',
      subtitle: 'Will close automatically in 10 seconds',
      primaryColor: Colors.orange,
      timeout: Duration(seconds: 10),
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Timed Scan Result', result);
    } else {
      _showSnackBar('Scan timed out or cancelled', Colors.orange);
    }
  }

  // Example 6: Flash Disabled Scanner
  Future<void> _scanWithoutFlash() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '🔦 No Flash Scanner',
      subtitle: 'Flash toggle disabled',
      primaryColor: Colors.teal,
      allowFlashToggle: false,
      allowCameraToggle: true,
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('No Flash Scan', result);
    }
  }

  // Example 7: Camera Toggle Disabled
  Future<void> _scanWithoutCameraToggle() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '📷 Fixed Camera',
      subtitle: 'Camera switch disabled',
      primaryColor: Colors.indigo,
      allowFlashToggle: true,
      allowCameraToggle: false,
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Fixed Camera Scan', result);
    }
  }

  // Example 8: All Features Disabled
  Future<void> _minimalScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '🔒 Minimal Scanner',
      subtitle: 'No controls available',
      primaryColor: Colors.grey,
      allowFlashToggle: false,
      allowCameraToggle: false,
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Minimal Scan', result);
    }
  }

  // Example 9: Product Barcode Scanner
  Future<void> _productScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '🛍️ Product Scanner',
      subtitle: 'Scan product barcode',
      primaryColor: Colors.green,
      backgroundColor: Colors.black,
    );

    if (result != null) {
      _addToHistory(result);
      
      // Check if it's a product barcode
      if (_isProductBarcode(result.format)) {
        _showProductInfo(result);
      } else {
        _showResultDialog('Product Scan', result);
      }
    }
  }

  // Example 10: QR Code Only Scanner
  Future<void> _qrOnlyScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '📱 QR Code Only',
      subtitle: 'Only QR codes will be detected',
      primaryColor: Colors.blue,
    );

    if (result != null) {
      if (result.format == BarcodeFormat.qrcode) {
        _addToHistory(result);
        _handleQRCode(result);
      } else {
        _showSnackBar('Please scan a QR code only', Colors.orange);
      }
    }
  }

  // Example 11: Gradient Background Scanner
  Future<void> _gradientScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '🌈 Gradient Scanner',
      subtitle: 'Beautiful gradient background',
      primaryColor: Colors.pink,
      backgroundColor: Colors.purple.shade900,
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Gradient Scan', result);
    }
  }

  // Example 12: Long Timeout Scanner
  Future<void> _longTimeoutScan() async {
    if (!isPermissionGranted) {
      await _requestPermission();
      return;
    }

    final result = await QRBarcodeScanner.showScannerDialog(
      context,
      title: '⏳ Extended Scanner',
      subtitle: 'Will timeout in 2 minutes',
      primaryColor: Colors.deepOrange,
      timeout: Duration(minutes: 2),
    );

    if (result != null) {
      _addToHistory(result);
      _showResultDialog('Extended Scan', result);
    }
  }

  // Helper Methods

  void _addToHistory(ScannerResult result) {
    setState(() {
      scanHistory.insert(0, result);
      // Keep only last 20 scans
      if (scanHistory.length > 20) {
        scanHistory.removeLast();
      }
    });
  }

  bool _isProductBarcode(BarcodeFormat format) {
    return [
      BarcodeFormat.ean13,
      BarcodeFormat.ean8,
      BarcodeFormat.upca,
      BarcodeFormat.upce,
    ].contains(format);
  }

  void _handleQRCode(ScannerResult result) {
    final code = result.code;
    
    if (code.startsWith('http://') || code.startsWith('https://')) {
      _showURLDialog(result);
    } else if (code.startsWith('WIFI:')) {
      _showWiFiDialog(result);
    } else if (code.startsWith('mailto:')) {
      _showEmailDialog(result);
    } else if (code.startsWith('tel:')) {
      _showPhoneDialog(result);
    } else {
      _showResultDialog('QR Code Scan', result);
    }
  }

  void _showResultDialog(String title, ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text(title),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Code: ${result.code}'),
            SizedBox(height: 8),
            Text('Format: ${result.format.toString().split('.').last}'),
            SizedBox(height: 8),
            Text('Time: ${result.timestamp.toString()}'),
            SizedBox(height: 16),
            Text('JSON:'),
            Container(
              padding: EdgeInsets.all(8),
              decoration: BoxDecoration(
                color: Colors.grey[200],
                borderRadius: BorderRadius.circular(4),
              ),
              child: Text(
                result.toJson().toString(),
                style: TextStyle(fontSize: 12),
              ),
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () {
              Clipboard.setData(ClipboardData(text: result.code));
              Navigator.of(context).pop();
              _showSnackBar('Copied to clipboard', Colors.green);
            },
            child: Text('Copy'),
          ),
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('Close'),
          ),
        ],
      ),
    );
  }

  void _showProductInfo(ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('🛍️ Product Detected'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('Product Code: ${result.code}'),
            Text('Format: ${result.format.toString().split('.').last}'),
            SizedBox(height: 16),
            Text('This appears to be a product barcode!'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  void _showURLDialog(ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('🌐 URL Detected'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('URL: ${result.code}'),
            SizedBox(height: 16),
            Text('Would you like to open this URL?'),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              Navigator.of(context).pop();
              _showSnackBar('URL: ${result.code}', Colors.blue);
            },
            child: Text('Open'),
          ),
        ],
      ),
    );
  }

  void _showWiFiDialog(ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('📶 WiFi Config'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text('WiFi Configuration Detected'),
            SizedBox(height: 8),
            Text(result.code),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  void _showEmailDialog(ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('📧 Email'),
        content: Text('Email: ${result.code}'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  void _showPhoneDialog(ScannerResult result) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('📞 Phone'),
        content: Text('Phone: ${result.code}'),
        actions: [
          TextButton(
            onPressed: () => Navigator.of(context).pop(),
            child: Text('OK'),
          ),
        ],
      ),
    );
  }

  void _showSnackBar(String message, Color color) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        backgroundColor: color,
        duration: Duration(seconds: 2),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('QR Barcode Scanner Examples'),
        backgroundColor: Colors.blue.shade700,
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            // Permission Status
            Card(
              color: isPermissionGranted ? Colors.green.shade50 : Colors.red.shade50,
              child: Padding(
                padding: EdgeInsets.all(16),
                child: Row(
                  children: [
                    Icon(
                      isPermissionGranted ? Icons.check_circle : Icons.error,
                      color: isPermissionGranted ? Colors.green : Colors.red,
                    ),
                    SizedBox(width: 8),
                    Expanded(
                      child: Text(
                        isPermissionGranted 
                          ? 'Camera permission granted' 
                          : 'Camera permission required',
                        style: TextStyle(
                          color: isPermissionGranted ? Colors.green.shade700 : Colors.red.shade700,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                    if (!isPermissionGranted)
                      ElevatedButton(
                        onPressed: _requestPermission,
                        child: Text('Grant'),
                      ),
                  ],
                ),
              ),
            ),
            
            SizedBox(height: 20),
            
            // Basic Examples
            Text('Basic Examples', style: Theme.of(context).textTheme.headlineSmall),
            SizedBox(height: 10),
            
            _buildExampleButton(
              'Basic Scanner',
              'Simple scan with default settings',
              Icons.qr_code_scanner,
              Colors.blue,
              _basicScan,
            ),
            
            _buildExampleButton(
              'Custom Styled Scanner',
              'Scanner with custom colors and styling',
              Icons.palette,
              Colors.purple,
              _customStyledScan,
            ),
            
            _buildExampleButton(
              'Scanner with Timeout',
              'Auto-close after 10 seconds',
              Icons.timer,
              Colors.orange,
              _scanWithTimeout,
            ),
            
            SizedBox(height: 20),
            
            // Feature Control Examples
            Text('Feature Control Examples', style: Theme.of(context).textTheme.headlineSmall),
            SizedBox(height: 10),
            
            _buildExampleButton(
              'No Flash Toggle',
              'Scanner without flash control',
              Icons.flash_off,
              Colors.teal,
              _scanWithoutFlash,
            ),
            
            _buildExampleButton(
              'No Camera Toggle',
              'Scanner without camera switching',
              Icons.camera_alt,
              Colors.indigo,
              _scanWithoutCameraToggle,
            ),
            
            _buildExampleButton(
              'Minimal Scanner',
              'Basic scanner with no extra controls',
              Icons.minimize,
              Colors.grey,
              _minimalScan,
            ),
            
            SizedBox(height: 20),
            
            // Specialized Examples
            Text('Specialized Examples', style: Theme.of(context).textTheme.headlineSmall),
            SizedBox(height: 10),
            
            _buildExampleButton(
              'Product Scanner',
              'Optimized for product barcodes',
              Icons.shopping_cart,
              Colors.green,
              _productScan,
            ),
            
            _buildExampleButton(
              'QR Code Only',
              'Filters only QR codes',
              Icons.qr_code,
              Colors.blue,
              _qrOnlyScan,
            ),
            
            _buildExampleButton(
              'Gradient Background',
              'Beautiful gradient styling',
              Icons.gradient,
              Colors.pink,
              _gradientScan,
            ),
            
            _buildExampleButton(
              'Extended Timeout',
              'Scanner with 2-minute timeout',
              Icons.access_time,
              Colors.deepOrange,
              _longTimeoutScan,
            ),
            
            SizedBox(height: 20),
            
            // Scan History
            if (scanHistory.isNotEmpty) ...[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text('Scan History', style: Theme.of(context).textTheme.headlineSmall),
                  TextButton(
                    onPressed: () {
                      setState(() {
                        scanHistory.clear();
                      });
                    },
                    child: Text('Clear'),
                  ),
                ],
              ),
              SizedBox(height: 10),
              ...scanHistory.take(5).map((result) => _buildHistoryItem(result)),
              if (scanHistory.length > 5)
                TextButton(
                  onPressed: () => _showAllHistory(),
                  child: Text('View All (${scanHistory.length})'),
                ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildExampleButton(
    String title,
    String subtitle,
    IconData icon,
    Color color,
    VoidCallback onPressed,
  ) {
    return Card(
      margin: EdgeInsets.only(bottom: 8),
      child: ListTile(
        leading: Container(
          padding: EdgeInsets.all(8),
          decoration: BoxDecoration(
            color: color.withOpacity(0.1),
            borderRadius: BorderRadius.circular(8),
          ),
          child: Icon(icon, color: color),
        ),
        title: Text(title),
        subtitle: Text(subtitle),
        trailing: Icon(Icons.arrow_forward_ios, size: 16),
        onTap: onPressed,
      ),
    );
  }

  Widget _buildHistoryItem(ScannerResult result) {
    return Card(
      margin: EdgeInsets.only(bottom: 4),
      child: ListTile(
        leading: Icon(_getFormatIcon(result.format)),
        title: Text(
          result.code,
          maxLines: 1,
          overflow: TextOverflow.ellipsis,
        ),
        subtitle: Text(
          '${result.format.toString().split('.').last} • ${_formatTime(result.timestamp)}',
        ),
        onTap: () => _showResultDialog('History Item', result),
      ),
    );
  }

  IconData _getFormatIcon(BarcodeFormat format) {
    switch (format) {
      case BarcodeFormat.qrcode:
        return Icons.qr_code;
      case BarcodeFormat.ean13:
      case BarcodeFormat.ean8:
      case BarcodeFormat.upca:
      case BarcodeFormat.upce:
        return Icons.shopping_cart;
      default:
        return Icons.code;
    }
  }

  String _formatTime(DateTime time) {
    final now = DateTime.now();
    final diff = now.difference(time);
    
    if (diff.inMinutes < 1) {
      return 'Just now';
    } else if (diff.inHours < 1) {
      return '${diff.inMinutes}m ago';
    } else if (diff.inDays < 1) {
      return '${diff.inHours}h ago';
    } else {
      return '${diff.inDays}d ago';
    }
  }

  void _showAllHistory() {
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) => HistoryPage(scanHistory: scanHistory),
      ),
    );
  }
}

// Separate page for full history
class HistoryPage extends StatelessWidget {
  final List<ScannerResult> scanHistory;
  
  const HistoryPage({Key? key, required this.scanHistory}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Scan History'),
        backgroundColor: Colors.blue.shade700,
      ),
      body: ListView.builder(
        padding: EdgeInsets.all(16),
        itemCount: scanHistory.length,
        itemBuilder: (context, index) {
          final result = scanHistory[index];
          return Card(
            margin: EdgeInsets.only(bottom: 8),
            child: ListTile(
              leading: Icon(_getFormatIcon(result.format)),
              title: Text(result.code),
              subtitle: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text('Format: ${result.format.toString().split('.').last}'),
                  Text('Time: ${result.timestamp.toString()}'),
                ],
              ),
              onTap: () {
                Clipboard.setData(ClipboardData(text: result.code));
                ScaffoldMessenger.of(context).showSnackBar(
                  SnackBar(content: Text('Copied to clipboard')),
                );
              },
            ),
          );
        },
      ),
    );
  }

  IconData _getFormatIcon(BarcodeFormat format) {
    switch (format) {
      case BarcodeFormat.qrcode:
        return Icons.qr_code;
      case BarcodeFormat.ean13:
      case BarcodeFormat.ean8:
      case BarcodeFormat.upca:
      case BarcodeFormat.upce:
        return Icons.shopping_cart;
      default:
        return Icons.code;
    }
  }
}
4
likes
0
points
91
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter package for scanning QR codes and barcodes using a dialog.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, permission_handler, qr_code_scanner

More

Packages that depend on qr_barcode_dialog_scanner