You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
5.9 KiB
207 lines
5.9 KiB
// Ajoutez cette importation en haut du fichier
|
|
import 'dart:ui';
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:mobile_scanner/mobile_scanner.dart';
|
|
|
|
// Créez une nouvelle classe pour la page de scan QR
|
|
class ScanQRPage extends StatefulWidget {
|
|
const ScanQRPage({super.key});
|
|
|
|
@override
|
|
State<ScanQRPage> createState() => _ScanQRPageState();
|
|
}
|
|
|
|
class _ScanQRPageState extends State<ScanQRPage> {
|
|
MobileScannerController cameraController = MobileScannerController();
|
|
bool _isScanComplete = false;
|
|
String? _scannedData;
|
|
|
|
@override
|
|
void dispose() {
|
|
cameraController.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text('Scanner QR Code'),
|
|
actions: [
|
|
IconButton(
|
|
color: Colors.white,
|
|
icon: ValueListenableBuilder(
|
|
valueListenable: cameraController.torchState,
|
|
builder: (context, state, child) {
|
|
switch (state) {
|
|
case TorchState.off:
|
|
return const Icon(Icons.flash_off, color: Colors.grey);
|
|
case TorchState.on:
|
|
return const Icon(Icons.flash_on, color: Colors.yellow);
|
|
}
|
|
},
|
|
),
|
|
iconSize: 32.0,
|
|
onPressed: () => cameraController.toggleTorch(),
|
|
),
|
|
IconButton(
|
|
color: Colors.white,
|
|
icon: ValueListenableBuilder(
|
|
valueListenable: cameraController.cameraFacingState,
|
|
builder: (context, state, child) {
|
|
switch (state) {
|
|
case CameraFacing.front:
|
|
return const Icon(Icons.camera_front);
|
|
case CameraFacing.back:
|
|
return const Icon(Icons.camera_rear);
|
|
}
|
|
},
|
|
),
|
|
iconSize: 32.0,
|
|
onPressed: () => cameraController.switchCamera(),
|
|
),
|
|
],
|
|
),
|
|
body: Stack(
|
|
children: [
|
|
MobileScanner(
|
|
controller: cameraController,
|
|
onDetect: (capture) {
|
|
final List<Barcode> barcodes = capture.barcodes;
|
|
for (final barcode in barcodes) {
|
|
if (!_isScanComplete && barcode.rawValue != null) {
|
|
_isScanComplete = true;
|
|
_scannedData = barcode.rawValue;
|
|
_showScanResult(context, _scannedData!);
|
|
}
|
|
}
|
|
},
|
|
),
|
|
CustomPaint(
|
|
painter: QrScannerOverlay(
|
|
borderColor: Colors.blue.shade800,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showScanResult(BuildContext context, String data) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: const Text('Résultat du scan'),
|
|
content: Text(data),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
setState(() {
|
|
_isScanComplete = false;
|
|
});
|
|
},
|
|
child: const Text('OK'),
|
|
),
|
|
],
|
|
),
|
|
).then((_) {
|
|
// Réinitialiser le scan après la fermeture du dialogue
|
|
setState(() {
|
|
_isScanComplete = false;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
|
|
// Widget personnalisé pour l'overlay du scanner
|
|
class QrScannerOverlay extends CustomPainter {
|
|
final Color borderColor;
|
|
|
|
QrScannerOverlay({required this.borderColor});
|
|
|
|
@override
|
|
void paint(Canvas canvas, Size size) {
|
|
final double width = size.width;
|
|
final double height = size.height;
|
|
final double borderWidth = 2.0;
|
|
final double borderLength = 30.0;
|
|
final double areaSize = width * 0.7;
|
|
|
|
// Dessiner un rectangle semi-transparent autour de la zone de scan
|
|
final Paint backgroundPaint = Paint()
|
|
..color = Colors.black.withOpacity(0.4);
|
|
canvas.drawRect(Rect.fromLTRB(0, 0, width, height), backgroundPaint);
|
|
|
|
// Dessiner la zone de scan transparente
|
|
final Paint transparentPaint = Paint()
|
|
..color = Colors.transparent
|
|
..blendMode = BlendMode.clear;
|
|
final double areaLeft = (width - areaSize) / 2;
|
|
final double areaTop = (height - areaSize) / 2;
|
|
canvas.drawRect(
|
|
Rect.fromLTRB(areaLeft, areaTop, areaLeft + areaSize, areaTop + areaSize),
|
|
transparentPaint,
|
|
);
|
|
|
|
// Dessiner les bordures de la zone de scan
|
|
final Paint borderPaint = Paint()
|
|
..color = borderColor
|
|
..strokeWidth = borderWidth
|
|
..style = PaintingStyle.stroke;
|
|
|
|
// Coin supérieur gauche
|
|
canvas.drawLine(
|
|
Offset(areaLeft, areaTop),
|
|
Offset(areaLeft + borderLength, areaTop),
|
|
borderPaint,
|
|
);
|
|
canvas.drawLine(
|
|
Offset(areaLeft, areaTop),
|
|
Offset(areaLeft, areaTop + borderLength),
|
|
borderPaint,
|
|
);
|
|
|
|
// Coin supérieur droit
|
|
canvas.drawLine(
|
|
Offset(areaLeft + areaSize - borderLength, areaTop),
|
|
Offset(areaLeft + areaSize, areaTop),
|
|
borderPaint,
|
|
);
|
|
canvas.drawLine(
|
|
Offset(areaLeft + areaSize, areaTop),
|
|
Offset(areaLeft + areaSize, areaTop + borderLength),
|
|
borderPaint,
|
|
);
|
|
|
|
// Coin inférieur gauche
|
|
canvas.drawLine(
|
|
Offset(areaLeft, areaTop + areaSize - borderLength),
|
|
Offset(areaLeft, areaTop + areaSize),
|
|
borderPaint,
|
|
);
|
|
canvas.drawLine(
|
|
Offset(areaLeft, areaTop + areaSize),
|
|
Offset(areaLeft + borderLength, areaTop + areaSize),
|
|
borderPaint,
|
|
);
|
|
|
|
// Coin inférieur droit
|
|
canvas.drawLine(
|
|
Offset(areaLeft + areaSize - borderLength, areaTop + areaSize),
|
|
Offset(areaLeft + areaSize, areaTop + areaSize),
|
|
borderPaint,
|
|
);
|
|
canvas.drawLine(
|
|
Offset(areaLeft + areaSize, areaTop + areaSize - borderLength),
|
|
Offset(areaLeft + areaSize, areaTop + areaSize),
|
|
borderPaint,
|
|
);
|
|
}
|
|
|
|
@override
|
|
bool shouldRepaint(covariant CustomPainter oldDelegate) {
|
|
return false;
|
|
}
|
|
}
|