ultra_qr_scanner 3.0.5 copy "ultra_qr_scanner: ^3.0.5" to clipboard
ultra_qr_scanner: ^3.0.5 copied to clipboard

Ultra-fast, low-latency QR code & Barcode scanner plugin for Flutter with native performance optimization.

example/lib/main.dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:ultra_qr_scanner/ultra_qr_scanner.dart';
import 'package:ultra_qr_scanner/ultra_qr_scanner_widget.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Ultra QR Scanner',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  String? _lastScannedCode;
  bool _useAutoStart = true;
  String _debugInfo = '';
  bool _permissionGranted = false;

  @override
  void initState() {
    super.initState();
    if (Platform.isIOS) {
      // iOS: the scanner widget handles permission natively via AVFoundation
      setState(() {
        _permissionGranted = true;
        _debugInfo = '';
      });
    } else {
      _requestPermission();
    }
  }

  Future<void> _requestPermission() async {
    setState(() => _debugInfo = 'Requesting camera permission...');

    final status = await Permission.camera.request();

    if (status.isGranted) {
      setState(() {
        _permissionGranted = true;
        _debugInfo = 'Camera permission granted.';
      });
    } else if (status.isPermanentlyDenied) {
      setState(() => _debugInfo = 'Permission permanently denied. Open settings to enable.');
    } else {
      setState(() => _debugInfo = 'Camera permission denied.');
    }
  }

  Future<void> _openSettings() async {
    await openAppSettings();
    final status = await Permission.camera.status;
    if (status.isGranted && mounted) {
      setState(() {
        _permissionGranted = true;
        _debugInfo = 'Camera permission granted.';
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Ultra QR Scanner'),
        actions: [
          // Toggle button to switch between auto-start and manual start modes
          IconButton(
            icon: Icon(_useAutoStart ? Icons.play_circle_filled : Icons.play_circle_outline),
            onPressed: () {
              setState(() {
                _useAutoStart = !_useAutoStart;
              });
            },
            tooltip: _useAutoStart ? 'Switch to Manual Mode' : 'Switch to Auto Mode',
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              _useAutoStart
                  ? 'Auto-start mode: Scanning begins automatically'
                  : 'Manual mode: Tap Start Scan button to begin',
              style: const TextStyle(fontSize: 16),
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 10),

            // Mode indicator
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
              decoration: BoxDecoration(
                color: _useAutoStart ? Colors.green.shade100 : Colors.blue.shade100,
                borderRadius: BorderRadius.circular(20),
                border: Border.all(
                  color: _useAutoStart ? Colors.green : Colors.blue,
                  width: 1,
                ),
              ),
              child: Text(
                _useAutoStart ? '🚀 AUTO START' : '👆 MANUAL START',
                style: TextStyle(
                  fontSize: 12,
                  fontWeight: FontWeight.bold,
                  color: _useAutoStart ? Colors.green.shade800 : Colors.blue.shade800,
                ),
              ),
            ),

            const SizedBox(height: 20),

            // Debug info display
            if (_debugInfo.isNotEmpty)
              Container(
                padding: const EdgeInsets.all(12),
                margin: const EdgeInsets.symmetric(horizontal: 20),
                decoration: BoxDecoration(
                  color: _debugInfo.contains('Error') ? Colors.red.shade100 : Colors.blue.shade100,
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(
                    color: _debugInfo.contains('Error') ? Colors.red : Colors.blue,
                    width: 1,
                  ),
                ),
                child: Text(
                  'Debug: $_debugInfo',
                  style: TextStyle(
                    fontSize: 12,
                    color: _debugInfo.contains('Error') ? Colors.red.shade800 : Colors.blue.shade800,
                  ),
                  textAlign: TextAlign.center,
                ),
              ),

            const SizedBox(height: 20),

            // Show scanner widget only after permission is granted
            if (_permissionGranted)
              Container(
                width: 300,
                height: 300,
                decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(12),
                  boxShadow: [
                    BoxShadow(
                      color: Colors.black.withValues(alpha: 0.2),
                      blurRadius: 8,
                      offset: const Offset(0, 2),
                    ),
                  ],
                ),
                child: UltraQrScannerWidget(
                  onCodeDetected: (code, type) {
                    setState(() {
                      _lastScannedCode = code;
                    });
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(
                        content: Text('Scanned: $code'),
                        backgroundColor: Colors.green,
                        behavior: SnackBarBehavior.floating,
                        duration: const Duration(seconds: 2),
                      ),
                    );
                  },
                  showFlashToggle: true,
                  autoStop: true,
                  showStartStopButton: !_useAutoStart,
                  autoStart: _useAutoStart,
                ),
              )
            else
              Column(
                children: [
                  const Icon(Icons.camera_alt_outlined, size: 64, color: Colors.grey),
                  const SizedBox(height: 12),
                  const Text('Camera permission is required to scan QR codes.'),
                  const SizedBox(height: 12),
                  ElevatedButton.icon(
                    onPressed: _debugInfo.contains('permanently')
                        ? _openSettings
                        : _requestPermission,
                    icon: const Icon(Icons.lock_open),
                    label: Text(_debugInfo.contains('permanently')
                        ? 'Open Settings'
                        : 'Grant Permission'),
                  ),
                ],
              ),

            const SizedBox(height: 20),

            // Results display
            Container(
              padding: const EdgeInsets.all(16),
              margin: const EdgeInsets.symmetric(horizontal: 20),
              decoration: BoxDecoration(
                color: Colors.grey.shade100,
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.grey.shade300),
              ),
              child: Column(
                children: [
                  const Text(
                    'Last Scanned Code:',
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                      color: Colors.grey,
                    ),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    _lastScannedCode ?? 'No QR code scanned yet',
                    style: const TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.w500,
                    ),
                    textAlign: TextAlign.center,
                  ),
                ],
              ),
            ),

            const SizedBox(height: 20),

            // Usage examples
            Container(
              padding: const EdgeInsets.all(16),
              margin: const EdgeInsets.symmetric(horizontal: 20),
              decoration: BoxDecoration(
                color: Colors.blue.shade50,
                borderRadius: BorderRadius.circular(8),
                border: Border.all(color: Colors.blue.shade200),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  const Text(
                    '💡 Usage Modes:',
                    style: TextStyle(
                      fontSize: 16,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                  const SizedBox(height: 8),
                  const Text('🚀 Auto-start: Scanning begins immediately'),
                  const Text('👆 Manual: User controls start/stop'),
                  const Text('⚡ Both modes auto-stop after detection'),
                  const SizedBox(height: 8),
                  Text(
                    'Current: ${_useAutoStart ? "Auto-start mode" : "Manual mode"}',
                    style: const TextStyle(
                      fontWeight: FontWeight.w600,
                      fontStyle: FontStyle.italic,
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// Example of different usage scenarios:

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Auto Scanner')),
      body: UltraQrScannerWidget(
        onCodeDetected: (code , type) {
          Navigator.pop(context, code);
        },
        showFlashToggle: true,
        autoStop: true,
        showStartStopButton: false, // Hide button
        autoStart: true,            // Auto-start scanning
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Manual Scanner')),
      body: UltraQrScannerWidget(
        onCodeDetected: (code, type) {
          Navigator.pop(context, code);
        },
        showFlashToggle: true,
        autoStop: true,
        showStartStopButton: true, // Show button
        autoStart: false,          // Manual start
      ),
    );
  }
}
10
likes
150
points
257
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Ultra-fast, low-latency QR code & Barcode scanner plugin for Flutter with native performance optimization.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on ultra_qr_scanner

Packages that implement ultra_qr_scanner