qr_barcode_dialog_scanner 1.0.0
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;
}
}
}