jjsos_autosos_flutter/lib/pages/common/qr_scan_page.dart

136 lines
3.7 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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<QrScanPage> createState() => _QrScanPageState();
}
class _QrScanPageState extends State<QrScanPage> {
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<void> _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),
),
),
),
),
],
),
);
}
}