Skip to content

Commit

Permalink
655: add overlay shape
Browse files Browse the repository at this point in the history
  • Loading branch information
sarahsporck committed Jan 9, 2023
1 parent 77ff0f6 commit 521e895
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 11 deletions.
3 changes: 2 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@
"args": [
"flutter",
"run",
"--dart-define=environment=local"
"--dart-define=environment=local",
"--flavor=Bayern"
],
"problemMatcher": [
"$gradle"
Expand Down
2 changes: 1 addition & 1 deletion frontend/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ android {
}

defaultConfig {
minSdkVersion 20
minSdkVersion 21
targetSdkVersion 33
multiDexEnabled true
versionCode flutterVersionCode.toInteger()
Expand Down
19 changes: 10 additions & 9 deletions frontend/lib/qr_code_scanner/qr_code_scanner.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'dart:math';

import 'package:ehrenamtskarte/qr_code_scanner/qr_code_scanner_controls.dart';
import 'package:ehrenamtskarte/qr_code_scanner/qr_overlay_shape.dart';
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

Expand Down Expand Up @@ -40,17 +41,17 @@ class _QRViewState extends State<QrCodeScanner> {
allowDuplicates: false,
controller: controller,
),
Center(
Padding(
padding: EdgeInsets.zero,
child: Container(
width: _calculateScanArea(context),
height: _calculateScanArea(context),
decoration: BoxDecoration(
color: Colors.transparent,
border: Border.all(
color: Theme.of(context).colorScheme.secondary,
width: 10,
decoration: ShapeDecoration(
shape: QrScannerOverlayShape(
borderRadius: 10,
borderColor: Theme.of(context).colorScheme.secondary,
borderLength: 30,
borderWidth: 10,
cutOutSize: _calculateScanArea(context),
),
borderRadius: const BorderRadius.all(Radius.circular(10.0)),
),
),
),
Expand Down
178 changes: 178 additions & 0 deletions frontend/lib/qr_code_scanner/qr_overlay_shape.dart
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,
);
}
}

0 comments on commit 521e895

Please sign in to comment.