Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do I draw a rectangular shape of all detected barcodes on the screen? #1222

Open
maxfrees opened this issue Oct 17, 2024 · 3 comments
Open

Comments

@maxfrees
Copy link

maxfrees commented Oct 17, 2024

How to draw a rectangular shape of all detected barcodes on the screen and click to select one to get content

Hope to provide docs examples

image

@navaronbracke
Copy link
Collaborator

You would have to use the corners and size of each of the barcodes to detect their size and center point in the image.

@maxfrees
Copy link
Author

Can you add a similar demo to the example, a lot of people need it

@karthiks3000
Copy link

I haven't tested this for multiple barcodes but this is what I implemented for helping detect a single barcode when scanning.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

class BarcodeScannerScreen extends StatefulWidget {
  @override
  State<BarcodeScannerScreen> createState() => _BarcodeScannerScreenState();
}

class _BarcodeScannerScreenState extends State<BarcodeScannerScreen> {
  bool _isScannerActive = true;
  bool _isFlashOn = false;
  MobileScannerController controller = MobileScannerController();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Scan Barcode'),
        actions: [
          IconButton(
            icon: Icon(_isFlashOn ? Icons.flash_on : Icons.flash_off),
            onPressed: () async {
              await controller.toggleTorch();
              setState(() {
                _isFlashOn = !_isFlashOn;
              });
            },
          ),
          IconButton(
            icon: const Icon(Icons.switch_camera),
            onPressed: () => controller.switchCamera(),
          ),
        ],
      ),
      body: Stack(
        children: [
          MobileScanner(
            controller: controller,
            fit: BoxFit.contain,
            scanWindow: Rect.fromCenter(
              center: Offset(
                MediaQuery.of(context).size.width / 2,
                MediaQuery.of(context).size.height / 2,
              ),
              width: 200,
              height: 200,
            ),
            onDetect: (capture) {
              if (!_isScannerActive) return;
              
              final List<Barcode> barcodes = capture.barcodes;
              for (final barcode in barcodes) {
                final String? code = barcode.rawValue;
                if (code != null) {
                  setState(() => _isScannerActive = false);
                  HapticFeedback.mediumImpact();
                  Navigator.of(context).pop(code);
                  return;
                }
              }
            },
          ),
          CustomPaint(
            size: Size.infinite,
            painter: ScannerOverlayPainter(),
          ),
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

class ScannerOverlayPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    final double scanAreaSize = 200;
    final double centerX = size.width / 2;
    final double centerY = size.height / 2;

    // Calculate scanner window coordinates
    final double left = centerX - scanAreaSize / 2;
    final double top = centerY - scanAreaSize / 2;
    final double right = centerX + scanAreaSize / 2;
    final double bottom = centerY + scanAreaSize / 2;

    // Draw scanner frame
    final Paint borderPaint = Paint()
      ..color = Colors.white
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3.0;

    // Draw corner markers
    final double markerLength = 30;
    
    // Top left corner
    canvas.drawLine(Offset(left, top), Offset(left + markerLength, top), borderPaint);
    canvas.drawLine(Offset(left, top), Offset(left, top + markerLength), borderPaint);

    // Top right corner
    canvas.drawLine(Offset(right - markerLength, top), Offset(right, top), borderPaint);
    canvas.drawLine(Offset(right, top), Offset(right, top + markerLength), borderPaint);

    // Bottom left corner
    canvas.drawLine(Offset(left, bottom - markerLength), Offset(left, bottom), borderPaint);
    canvas.drawLine(Offset(left, bottom), Offset(left + markerLength, bottom), borderPaint);

    // Bottom right corner
    canvas.drawLine(Offset(right - markerLength, bottom), Offset(right, bottom), borderPaint);
    canvas.drawLine(Offset(right, bottom - markerLength), Offset(right, bottom), borderPaint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => false;
}

And i've used it like this -

      final String? barcode = await Navigator.push<String>(
        context,
        MaterialPageRoute(
          builder: (context) => BarcodeScannerScreen(),
        ),
      );

This is what it should look like -
barcode_rect

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants