-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
77ff0f6
commit 521e895
Showing
4 changed files
with
191 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
import 'dart:math'; | ||
|
||
import 'package:flutter/material.dart'; | ||
|
||
// temporary solution | ||
// checkout https://github.com/juliansteenbakker/mobile_scanner/issues/250#issuecomment-1209723708 | ||
class QrScannerOverlayShape extends ShapeBorder { | ||
QrScannerOverlayShape({ | ||
this.borderColor = Colors.red, | ||
this.borderWidth = 3.0, | ||
this.overlayColor = const Color.fromRGBO(0, 0, 0, 80), | ||
this.borderRadius = 0, | ||
this.borderLength = 40, | ||
double? cutOutSize, | ||
double? cutOutWidth, | ||
double? cutOutHeight, | ||
this.cutOutBottomOffset = 0, | ||
}) : cutOutWidth = cutOutWidth ?? cutOutSize ?? 250, | ||
cutOutHeight = cutOutHeight ?? cutOutSize ?? 250 { | ||
assert( | ||
borderLength <= min(this.cutOutWidth, this.cutOutHeight) / 2 + borderWidth * 2, | ||
"Border can't be larger than ${min(this.cutOutWidth, this.cutOutHeight) / 2 + borderWidth * 2}", | ||
); | ||
// ignore: prefer_asserts_in_initializer_lists | ||
assert( | ||
(cutOutWidth == null && cutOutHeight == null) || | ||
(cutOutSize == null && cutOutWidth != null && cutOutHeight != null), | ||
'Use only cutOutWidth and cutOutHeight or only cutOutSize', | ||
); | ||
} | ||
|
||
final Color borderColor; | ||
final double borderWidth; | ||
final Color overlayColor; | ||
final double borderRadius; | ||
final double borderLength; | ||
final double cutOutWidth; | ||
final double cutOutHeight; | ||
final double cutOutBottomOffset; | ||
|
||
@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 width = rect.width; | ||
final borderWidthSize = width / 2; | ||
final height = rect.height; | ||
final borderOffset = borderWidth / 2; | ||
final _borderLength = | ||
borderLength > min(cutOutHeight, cutOutHeight) / 2 + borderWidth * 2 ? borderWidthSize / 2 : borderLength; | ||
final _cutOutWidth = cutOutWidth < width ? cutOutWidth : width - borderOffset; | ||
final _cutOutHeight = cutOutHeight < height ? cutOutHeight : height - borderOffset; | ||
|
||
final backgroundPaint = Paint() | ||
..color = overlayColor | ||
..style = PaintingStyle.fill; | ||
|
||
final borderPaint = Paint() | ||
..color = borderColor | ||
..style = PaintingStyle.stroke | ||
..strokeWidth = borderWidth; | ||
|
||
final boxPaint = Paint() | ||
..color = borderColor | ||
..style = PaintingStyle.fill | ||
..blendMode = BlendMode.dstOut; | ||
|
||
final cutOutRect = Rect.fromLTWH( | ||
rect.left + width / 2 - _cutOutWidth / 2 + borderOffset, | ||
-cutOutBottomOffset + rect.top + height / 2 - _cutOutHeight / 2 + borderOffset, | ||
_cutOutWidth - borderOffset * 2, | ||
_cutOutHeight - borderOffset * 2, | ||
); | ||
|
||
canvas | ||
..saveLayer( | ||
rect, | ||
backgroundPaint, | ||
) | ||
..drawRect( | ||
rect, | ||
backgroundPaint, | ||
) | ||
// Draw top right corner | ||
..drawRRect( | ||
RRect.fromLTRBAndCorners( | ||
cutOutRect.right - _borderLength, | ||
cutOutRect.top, | ||
cutOutRect.right, | ||
cutOutRect.top + _borderLength, | ||
topRight: Radius.circular(borderRadius), | ||
), | ||
borderPaint, | ||
) | ||
// Draw top left corner | ||
..drawRRect( | ||
RRect.fromLTRBAndCorners( | ||
cutOutRect.left, | ||
cutOutRect.top, | ||
cutOutRect.left + _borderLength, | ||
cutOutRect.top + _borderLength, | ||
topLeft: Radius.circular(borderRadius), | ||
), | ||
borderPaint, | ||
) | ||
// Draw bottom right corner | ||
..drawRRect( | ||
RRect.fromLTRBAndCorners( | ||
cutOutRect.right - _borderLength, | ||
cutOutRect.bottom - _borderLength, | ||
cutOutRect.right, | ||
cutOutRect.bottom, | ||
bottomRight: Radius.circular(borderRadius), | ||
), | ||
borderPaint, | ||
) | ||
// Draw bottom left corner | ||
..drawRRect( | ||
RRect.fromLTRBAndCorners( | ||
cutOutRect.left, | ||
cutOutRect.bottom - _borderLength, | ||
cutOutRect.left + _borderLength, | ||
cutOutRect.bottom, | ||
bottomLeft: Radius.circular(borderRadius), | ||
), | ||
borderPaint, | ||
) | ||
..drawRRect( | ||
RRect.fromRectAndRadius( | ||
cutOutRect, | ||
Radius.circular(borderRadius), | ||
), | ||
boxPaint, | ||
) | ||
..restore(); | ||
} | ||
|
||
@override | ||
ShapeBorder scale(double t) { | ||
return QrScannerOverlayShape( | ||
borderColor: borderColor, | ||
borderWidth: borderWidth, | ||
overlayColor: overlayColor, | ||
); | ||
} | ||
} |