Flutter plugin for scanning and generating QR codes using the ZXing library, supporting Android, iOS, and desktop platforms
flutterbarcode-generatorbarcode-scannergeneratorqrqrcodeqrcode-generatorqrcode-scannerscannerzxingbarcodezxscanner
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.
160 lines
4.2 KiB
160 lines
4.2 KiB
import 'package:flutter/material.dart'; |
|
|
|
class ScannerOverlay extends ShapeBorder { |
|
const ScannerOverlay({ |
|
this.borderColor = Colors.red, |
|
this.borderWidth = 3.0, |
|
this.overlayColor = const Color.fromRGBO(0, 0, 0, 40), |
|
this.borderRadius = 0, |
|
this.borderLength = 40, |
|
this.cutOutSize = 250, |
|
}) : assert(borderLength <= cutOutSize / 2 + borderWidth * 2, |
|
"Border can't be larger than ${cutOutSize / 2 + borderWidth * 2}"); |
|
|
|
final Color borderColor; |
|
final double borderWidth; |
|
final Color overlayColor; |
|
final double borderRadius; |
|
final double borderLength; |
|
final double cutOutSize; |
|
|
|
@override |
|
EdgeInsetsGeometry get dimensions => const EdgeInsets.all(10); |
|
|
|
@override |
|
Path getInnerPath(Rect rect, {TextDirection? textDirection}) { |
|
return Path() |
|
..fillType = PathFillType.evenOdd |
|
..addPath(getOuterPath(rect), Offset.zero); |
|
} |
|
|
|
@override |
|
Path getOuterPath(Rect rect, {TextDirection? textDirection}) { |
|
Path _getLeftTopPath(Rect rect) { |
|
return Path() |
|
..moveTo(rect.left, rect.bottom) |
|
..lineTo(rect.left, rect.top) |
|
..lineTo(rect.right, rect.top); |
|
} |
|
|
|
return _getLeftTopPath(rect) |
|
..lineTo( |
|
rect.right, |
|
rect.bottom, |
|
) |
|
..lineTo( |
|
rect.left, |
|
rect.bottom, |
|
) |
|
..lineTo( |
|
rect.left, |
|
rect.top, |
|
); |
|
} |
|
|
|
@override |
|
void paint(Canvas canvas, Rect rect, {TextDirection? textDirection}) { |
|
final double width = rect.width; |
|
final double borderWidthSize = width / 2; |
|
final double height = rect.height; |
|
final double borderOffset = borderWidth / 2; |
|
final double newBorderLength = |
|
borderLength > cutOutSize / 2 + borderWidth * 2 |
|
? borderWidthSize / 2 |
|
: borderLength; |
|
final double newCutOutSize = |
|
cutOutSize < width ? cutOutSize : width - borderOffset; |
|
|
|
final Paint backgroundPaint = Paint() |
|
..color = overlayColor |
|
..style = PaintingStyle.fill; |
|
|
|
final Paint borderPaint = Paint() |
|
..color = borderColor |
|
..style = PaintingStyle.stroke |
|
..strokeWidth = borderWidth; |
|
|
|
final Paint boxPaint = Paint() |
|
..color = borderColor |
|
..style = PaintingStyle.fill |
|
..blendMode = BlendMode.dstOut; |
|
|
|
final Rect cutOutRect = Rect.fromLTWH( |
|
rect.left + width / 2 - newCutOutSize / 2 + borderOffset, |
|
rect.top + height / 2 - newCutOutSize / 2 + borderOffset, |
|
newCutOutSize - borderOffset * 2, |
|
newCutOutSize - borderOffset * 2, |
|
); |
|
|
|
canvas |
|
..saveLayer( |
|
rect, |
|
backgroundPaint, |
|
) |
|
..drawRect( |
|
rect, |
|
backgroundPaint, |
|
) |
|
// Draw top right corner |
|
..drawRRect( |
|
RRect.fromLTRBAndCorners( |
|
cutOutRect.right - newBorderLength, |
|
cutOutRect.top, |
|
cutOutRect.right, |
|
cutOutRect.top + newBorderLength, |
|
topRight: Radius.circular(borderRadius), |
|
), |
|
borderPaint, |
|
) |
|
// Draw top left corner |
|
..drawRRect( |
|
RRect.fromLTRBAndCorners( |
|
cutOutRect.left, |
|
cutOutRect.top, |
|
cutOutRect.left + newBorderLength, |
|
cutOutRect.top + newBorderLength, |
|
topLeft: Radius.circular(borderRadius), |
|
), |
|
borderPaint, |
|
) |
|
// Draw bottom right corner |
|
..drawRRect( |
|
RRect.fromLTRBAndCorners( |
|
cutOutRect.right - newBorderLength, |
|
cutOutRect.bottom - newBorderLength, |
|
cutOutRect.right, |
|
cutOutRect.bottom, |
|
bottomRight: Radius.circular(borderRadius), |
|
), |
|
borderPaint, |
|
) |
|
// Draw bottom left corner |
|
..drawRRect( |
|
RRect.fromLTRBAndCorners( |
|
cutOutRect.left, |
|
cutOutRect.bottom - newBorderLength, |
|
cutOutRect.left + newBorderLength, |
|
cutOutRect.bottom, |
|
bottomLeft: Radius.circular(borderRadius), |
|
), |
|
borderPaint, |
|
) |
|
..drawRRect( |
|
RRect.fromRectAndRadius( |
|
cutOutRect, |
|
Radius.circular(borderRadius), |
|
), |
|
boxPaint, |
|
) |
|
..restore(); |
|
} |
|
|
|
@override |
|
ShapeBorder scale(double t) { |
|
return ScannerOverlay( |
|
borderColor: borderColor, |
|
borderWidth: borderWidth, |
|
overlayColor: overlayColor, |
|
); |
|
} |
|
}
|
|
|