juliansteenbakker / mobile_scanner

A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS.
BSD 3-Clause "New" or "Revised" License
744 stars 444 forks source link

Scan window doesn't work when using BoxFit.cover #1009

Open enricocaliolo opened 1 month ago

enricocaliolo commented 1 month ago

Hi, I can't seem to make scan window work when I use BoxFit.cover instead of BoxFit.contain. I think it is related to how I am painting the overlay scan, but dunno what to do.

Scaffold(
      appBar: AppBar(
        title: const Text('Escaneie o QR Code!'),
        backgroundColor: strongBlueColor(),
      ),
      backgroundColor: Colors.black,
      body: LayoutBuilder(builder: (context, constraints) {
        final scanWindow = Rect.fromCenter(
            center: Offset(constraints.maxWidth / 2, constraints.maxHeight / 2),
            width: 300,
            height: 300);

        return Stack(
          fit: StackFit.expand,
          children: [
            MobileScanner(
              onDetect: (capture) => _onDetected(capture, data_controller),
              controller: controller,
              fit: BoxFit.cover,
              scanWindow: scanWindow,
            ),
            if (started)
              CustomPaint(
                painter: ScannerOverlay(scanWindow),
              )
          ],
        );
      }),
    );

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);

    final backgroundPaint = Paint()
      ..color = Colors.black.withOpacity(0.5)
      ..style = PaintingStyle.fill
      ..blendMode = BlendMode.dstOut;

    final backgroundWithCutout = Path.combine(
      PathOperation.difference,
      backgroundPath,
      cutoutPath,
    );
    canvas.drawPath(backgroundWithCutout, backgroundPaint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}
navaronbracke commented 1 month ago

According to the docs at https://api.flutter.dev/flutter/painting/BoxFit.html BoxFit.cover means "as small as possible while still contained in the target box", while BoxFit.contain means "as large as possible [...]".

We do have a conversion at https://github.com/juliansteenbakker/mobile_scanner/blob/master/lib/src/scan_window_calculation.dart

However, that conversion seems to imply that the scan window is always centered when a BoxFit conversion is made.