Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import 'dart:async';
- import 'package:accurate_lite/core/components/page/scan/scanner_error_view.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter_hooks/flutter_hooks.dart';
- import 'package:mobile_scanner/mobile_scanner.dart';
- class FlexibleScanBarcode extends StatefulHookWidget {
- const FlexibleScanBarcode({
- super.key,
- this.descScannerText = '',
- this.isUseExternalScanner = true,
- required this.doOnDetect,
- required this.controller,
- });
- final String? descScannerText;
- final bool isUseExternalScanner;
- final Future Function(String _barcodeFound) doOnDetect;
- final MobileScannerController controller;
- @override
- State<FlexibleScanBarcode> createState() => _FlexibleScanBarcodeState();
- }
- class _FlexibleScanBarcodeState extends State<FlexibleScanBarcode>
- with SingleTickerProviderStateMixin {
- late AnimationController _animationController;
- String _barcodeFound = '';
- bool _isDetected = false;
- Barcode? barcode;
- BarcodeCapture? capture;
- Timer? _debounceTimer;
- @override
- void initState() {
- super.initState();
- _animationController = AnimationController(
- duration: const Duration(seconds: 1),
- reverseDuration: const Duration(seconds: 1),
- vsync: this,
- );
- widget.controller.start();
- _animationController.repeat(reverse: true);
- }
- @override
- void dispose() {
- widget.controller.dispose();
- _animationController.stop();
- _animationController.dispose();
- super.dispose();
- }
- void onDetect(BarcodeCapture barcode) async {
- if (_debounceTimer?.isActive ?? false) return;
- _debounceTimer = Timer(const Duration(milliseconds: 500), () async {
- capture = barcode;
- this.barcode = barcode.barcodes.first;
- for (final barcodes in capture!.barcodes) {
- _barcodeFound = barcodes.rawValue!;
- if (!_isDetected) {
- _isDetected = true;
- await widget.doOnDetect(_barcodeFound).then((value) {
- _isDetected = false;
- });
- _debounceTimer?.cancel();
- }
- }
- });
- }
- @override
- Widget build(BuildContext context) {
- const scanWindowWidthFactor = 0.9;
- double scanWindowHeightFactor = 0.8;
- double scanWindowTopFactor = 0.1;
- return LayoutBuilder(
- builder: (context, constraints) {
- if (constraints.maxHeight > 550) {
- scanWindowHeightFactor = 0.4;
- scanWindowTopFactor = 0.3;
- }
- final scanWindow = Rect.fromLTWH(
- constraints.maxWidth * (1 - scanWindowWidthFactor) / 2,
- constraints.maxHeight *
- scanWindowTopFactor, // Adjusted for half screen
- constraints.maxWidth * scanWindowWidthFactor,
- constraints.maxHeight * scanWindowHeightFactor,
- );
- return SizedBox(
- width: constraints.maxWidth,
- height: constraints.maxHeight,
- child: Stack(
- children: [
- MobileScanner(
- scanWindow: scanWindow,
- controller: widget.controller,
- errorBuilder: (context, error, child) {
- return ScannerErrorView(
- error: error,
- controller: widget.controller,
- );
- },
- onDetect: onDetect,
- ),
- // Overlay for scanner
- CustomPaint(
- size: Size(constraints.maxWidth, constraints.maxHeight),
- painter: ScannerOverlay(scanWindow),
- ),
- // Red line
- CustomPaint(
- size: Size(constraints.maxWidth, constraints.maxHeight),
- painter: RedLinePainter(
- animationController: _animationController,
- scanWindow: scanWindow,
- ),
- ),
- ],
- ),
- );
- },
- );
- }
- }
- class RedLinePainter extends CustomPainter {
- RedLinePainter({
- required this.animationController,
- required this.scanWindow,
- });
- final AnimationController animationController;
- final Rect scanWindow;
- late final Animation<double> _animation =
- Tween<double>(begin: 0, end: 1).animate(animationController);
- @override
- void paint(Canvas canvas, Size size) {
- final paint = Paint()
- ..color = Colors.red.withOpacity(_animation.value)
- ..strokeWidth = 2
- ..style = PaintingStyle.stroke
- ..strokeCap = StrokeCap.round;
- // Calculate line position based on scan window
- final centerY = scanWindow.top + (scanWindow.height * 0.5);
- canvas.drawLine(
- Offset(scanWindow.left + 20, centerY),
- Offset(scanWindow.right - 20, centerY),
- paint,
- );
- }
- @override
- bool shouldRepaint(RedLinePainter oldDelegate) => true;
- }
- class ScannerOverlay extends CustomPainter {
- ScannerOverlay(this.scanWindow);
- final Rect scanWindow;
- @override
- void paint(Canvas canvas, Size size) {
- final backgroundPath = Path()..addRect(Rect.largest);
- final cutoutPath = Path()..addRect(scanWindow);
- // Menggambar overlay hitam transparan
- canvas.drawPath(
- Path.combine(
- PathOperation.difference,
- backgroundPath,
- cutoutPath,
- ),
- Paint()..color = Colors.black.withOpacity(0.5),
- );
- // Menggambar border putih di sekitar area scanning
- final borderPaint = Paint()
- ..color = Colors.transparent
- ..style = PaintingStyle.stroke
- ..strokeWidth = 2.0;
- canvas.drawRect(scanWindow, borderPaint);
- }
- @override
- bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement