ultra_qr_scanner 3.0.5
ultra_qr_scanner: ^3.0.5 copied to clipboard
Ultra-fast, low-latency QR code & Barcode scanner plugin for Flutter with native performance optimization.
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
),
);
}
}