import 'package:autosos_flutter/util/toast.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:mobile_scanner/mobile_scanner.dart'; import 'package:permission_handler/permission_handler.dart'; /// 扫码页(对应 Android ScanActivity + zxing) class QrScanPage extends StatefulWidget { const QrScanPage({super.key}); @override State createState() => _QrScanPageState(); } class _QrScanPageState extends State { final MobileScannerController _controller = MobileScannerController( detectionSpeed: DetectionSpeed.normal, facing: CameraFacing.back, ); bool _handled = false; @override void initState() { super.initState(); _checkPermission(); } @override void dispose() { _controller.dispose(); super.dispose(); } Future _checkPermission() async { final cam = await Permission.camera.request(); if (!cam.isGranted) { if (mounted) { Toast.error('未授予相机权限'); context.pop(); } } } void _onDetect(BarcodeCapture capture) { if (_handled) return; for (final b in capture.barcodes) { final v = b.rawValue; if (v == null || v.isEmpty) continue; _handled = true; _controller.stop(); context.pop(v); return; } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, appBar: AppBar( backgroundColor: Colors.black, title: const Text('扫一扫'), iconTheme: const IconThemeData(color: Colors.white), actions: [ IconButton( icon: const Icon(Icons.flash_on), onPressed: () => _controller.toggleTorch(), ), IconButton( icon: const Icon(Icons.cameraswitch), onPressed: () => _controller.switchCamera(), ), ], ), body: Stack( children: [ MobileScanner( controller: _controller, onDetect: _onDetect, errorBuilder: (ctx, err, child) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ const Icon( Icons.error_outline, color: Colors.white, size: 48, ), const SizedBox(height: 8), Text( '相机错误:${err.errorCode.name}', style: const TextStyle(color: Colors.white), ), ], ), ); }, ), // 扫描框 Center( child: Container( width: 240, height: 240, decoration: BoxDecoration( border: Border.all(color: Colors.red, width: 2), borderRadius: BorderRadius.circular(12), ), ), ), // 顶部提示 Positioned( top: 16, left: 0, right: 0, child: Center( child: Container( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), decoration: BoxDecoration( color: Colors.black54, borderRadius: BorderRadius.circular(20), ), child: const Text( '将二维码/条码放入框内,自动扫描', style: TextStyle(color: Colors.white, fontSize: 12), ), ), ), ), ], ), ); } }