Sander Roest

wip

@@ -5,7 +5,6 @@ import 'package:flutter/services.dart'; @@ -5,7 +5,6 @@ import 'package:flutter/services.dart';
5 import 'package:mobile_scanner/mobile_scanner.dart'; 5 import 'package:mobile_scanner/mobile_scanner.dart';
6 import 'package:mobile_scanner_example/picklist/classes/detect_collision.dart'; 6 import 'package:mobile_scanner_example/picklist/classes/detect_collision.dart';
7 import 'package:mobile_scanner_example/picklist/widgets/crosshair.dart'; 7 import 'package:mobile_scanner_example/picklist/widgets/crosshair.dart';
8 -import 'package:mobile_scanner_example/picklist/widgets/draw_detected_barcodes.dart';  
9 import 'package:mobile_scanner_example/scanner_error_widget.dart'; 8 import 'package:mobile_scanner_example/scanner_error_widget.dart';
10 9
11 class BarcodeScannerPicklist extends StatefulWidget { 10 class BarcodeScannerPicklist extends StatefulWidget {
@@ -17,22 +16,16 @@ class BarcodeScannerPicklist extends StatefulWidget { @@ -17,22 +16,16 @@ class BarcodeScannerPicklist extends StatefulWidget {
17 16
18 class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> 17 class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist>
19 with WidgetsBindingObserver { 18 with WidgetsBindingObserver {
20 - final _mobileScannerController = MobileScannerController(autoStart: false); 19 + final _mobileScannerController = MobileScannerController(
  20 + autoStart: false,
  21 + );
21 StreamSubscription<Object?>? _barcodesSubscription; 22 StreamSubscription<Object?>? _barcodesSubscription;
22 23
23 final _scannerDisabled = ValueNotifier(false); 24 final _scannerDisabled = ValueNotifier(false);
24 25
25 - late final Offset _crosshair;  
26 -  
27 bool barcodeDetected = false; 26 bool barcodeDetected = false;
28 27
29 @override 28 @override
30 - void didChangeDependencies() {  
31 - _crosshair = MediaQuery.sizeOf(context).center(Offset.zero);  
32 - super.didChangeDependencies();  
33 - }  
34 -  
35 - @override  
36 void initState() { 29 void initState() {
37 SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); 30 SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
38 WidgetsBinding.instance.addObserver(this); 31 WidgetsBinding.instance.addObserver(this);
@@ -75,14 +68,17 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> @@ -75,14 +68,17 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist>
75 _mobileScannerController.dispose(); 68 _mobileScannerController.dispose();
76 } 69 }
77 70
78 - void _handleBarcodes(BarcodeCapture barcodes) { 71 + void _handleBarcodes(BarcodeCapture capture) {
79 if (_scannerDisabled.value) { 72 if (_scannerDisabled.value) {
80 return; 73 return;
81 } 74 }
82 75
83 - for (final barcode in barcodes.barcodes) {  
84 - if (isOffsetInsideShape(  
85 - _crosshair, 76 + for (final barcode in capture.barcodes) {
  77 + if (isPointInPolygon(
  78 + Offset(
  79 + _mobileScannerController.value.size.width / 2,
  80 + _mobileScannerController.value.size.height / 2,
  81 + ),
86 barcode.corners, 82 barcode.corners,
87 )) { 83 )) {
88 if (!barcodeDetected) { 84 if (!barcodeDetected) {
@@ -109,10 +105,6 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> @@ -109,10 +105,6 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist>
109 body: StreamBuilder( 105 body: StreamBuilder(
110 stream: _mobileScannerController.barcodes, 106 stream: _mobileScannerController.barcodes,
111 builder: (context, snapshot) { 107 builder: (context, snapshot) {
112 - final barcodes = snapshot.data;  
113 - if (barcodes == null) {  
114 - debugPrint('ISNULL');  
115 - }  
116 return Listener( 108 return Listener(
117 behavior: HitTestBehavior.opaque, 109 behavior: HitTestBehavior.opaque,
118 onPointerDown: (_) => _scannerDisabled.value = true, 110 onPointerDown: (_) => _scannerDisabled.value = true,
@@ -123,14 +115,8 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> @@ -123,14 +115,8 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist>
123 children: [ 115 children: [
124 MobileScanner( 116 MobileScanner(
125 controller: _mobileScannerController, 117 controller: _mobileScannerController,
126 - errorBuilder: (context, error, child) {  
127 - return ScannerErrorWidget(error: error);  
128 - },  
129 - fit: boxFit,  
130 - ),  
131 - ...drawDetectedBarcodes(  
132 - barcodes: barcodes?.barcodes,  
133 - cameraPreviewSize: _mobileScannerController.value.size, 118 + errorBuilder: (context, error, child) =>
  119 + ScannerErrorWidget(error: error),
134 fit: boxFit, 120 fit: boxFit,
135 ), 121 ),
136 ValueListenableBuilder( 122 ValueListenableBuilder(
@@ -145,51 +131,7 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist> @@ -145,51 +131,7 @@ class _BarcodeScannerPicklistState extends State<BarcodeScannerPicklist>
145 ), 131 ),
146 ); 132 );
147 }, 133 },
148 - )  
149 - // body: Stack(  
150 - // fit: StackFit.expand,  
151 - // children: [  
152 - // MobileScanner(  
153 - // controller: _mobileScannerController,  
154 - // errorBuilder: (context, error, child) {  
155 - // return ScannerErrorWidget(error: error);  
156 - // },  
157 - // fit: boxFit,  
158 - // ),  
159 - // ...drawDetectedBarcodes(  
160 - // controller: _mobileScannerController,  
161 - // cameraPreviewSize: _mobileScannerController.value.size,  
162 - // fit: boxFit,  
163 - // ),  
164 - // ...drawDetectedBarcodes(  
165 - // controller: _mobileScannerController,  
166 - // cameraPreviewSize: _mobileScannerController.value.size,  
167 - // fit: boxFit,  
168 - // ),  
169 - // // barcodes: _mobileScannerController. value. _barcodes.value,  
170 - // // cameraPreviewSize: _mobileScannerController.value.size,  
171 - // // fit: boxFit,  
172 - // // ),  
173 - // CustomPaint(  
174 - // painter: BarcodeOverlay(  
175 - // barcodeCorners: [  
176 - // const Offset(0, 0),  
177 - // const Offset(50, 0),  
178 - // const Offset(50, 50),  
179 - // const Offset(0, 50)  
180 - // ],  
181 - // barcodeSize: Size(50, 50),  
182 - // boxFit: boxFit,  
183 - // cameraPreviewSize: _mobileScannerController.value.size,  
184 - // ),  
185 - // ),  
186 - // Crosshair(  
187 - // crosshairRectangle: _crosshairRectangle,  
188 - // scannerDisabled: _scannerDisabled.value,  
189 - // ),  
190 - // ],  
191 - // ),  
192 - , 134 + ),
193 ), 135 ),
194 ); 136 );
195 } 137 }
1 -//Some magic created by chatGPT  
2 -  
3 import 'package:flutter/material.dart'; 1 import 'package:flutter/material.dart';
4 2
5 -bool isOffsetInsideShape(Offset point, List<Offset> shape) {  
6 - return _isPointInPolygon(shape, point);  
7 -}  
8 -  
9 -bool _isPointInPolygon(List<Offset> polygon, Offset point) {  
10 - // Use the ray-casting algorithm for checking if a point is inside a polygon 3 +bool isPointInPolygon(Offset point, List<Offset> polygon) {
  4 + int i;
  5 + int j = polygon.length - 1;
11 bool inside = false; 6 bool inside = false;
12 - for (int i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {  
13 - if ((polygon[i].dy > point.dy) != (polygon[j].dy > point.dy) && 7 +
  8 + for (i = 0; i < polygon.length; j = i++) {
  9 + if (((polygon[i].dy > point.dy) != (polygon[j].dy > point.dy)) &&
14 (point.dx < 10 (point.dx <
15 (polygon[j].dx - polygon[i].dx) * 11 (polygon[j].dx - polygon[i].dx) *
16 (point.dy - polygon[i].dy) / 12 (point.dy - polygon[i].dy) /
@@ -21,111 +17,3 @@ bool _isPointInPolygon(List<Offset> polygon, Offset point) { @@ -21,111 +17,3 @@ bool _isPointInPolygon(List<Offset> polygon, Offset point) {
21 } 17 }
22 return inside; 18 return inside;
23 } 19 }
24 -  
25 -// import 'package:flutter/material.dart';  
26 -//  
27 -// bool crosshairFullyFitsIntoShape(Rect rect, List<Offset> shape) {  
28 -// final List<Offset> rectCorners = [  
29 -// Offset(rect.left, rect.top),  
30 -// Offset(rect.right, rect.top),  
31 -// Offset(rect.right, rect.bottom),  
32 -// Offset(rect.left, rect.bottom),  
33 -// ];  
34 -//  
35 -// // Check if all rect corners are inside the shape  
36 -// for (final Offset corner in rectCorners) {  
37 -// if (!_isPointInPolygon(shape, corner)) {  
38 -// return false; // If any corner is outside, the rectangle doesn't fit fully  
39 -// }  
40 -// }  
41 -//  
42 -// return true; // All corners are inside the shape  
43 -// }  
44 -//  
45 -// bool _isPointInPolygon(List<Offset> polygon, Offset point) {  
46 -// // Use the ray-casting algorithm for checking if a point is inside a polygon  
47 -// bool inside = false;  
48 -// for (int i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {  
49 -// if ((polygon[i].dy > point.dy) != (polygon[j].dy > point.dy) &&  
50 -// (point.dx <  
51 -// (polygon[j].dx - polygon[i].dx) *  
52 -// (point.dy - polygon[i].dy) /  
53 -// (polygon[j].dy - polygon[i].dy) +  
54 -// polygon[i].dx)) {  
55 -// inside = !inside;  
56 -// }  
57 -// }  
58 -// return inside;  
59 -// }  
60 -// // import 'package:flutter/material.dart';  
61 -// //  
62 -// // bool crosshairTouchesBarcode(Rect rect, List<Offset> shape) {  
63 -// // final List<Offset> rectCorners = [  
64 -// // Offset(rect.left, rect.top),  
65 -// // Offset(rect.right, rect.top),  
66 -// // Offset(rect.right, rect.bottom),  
67 -// // Offset(rect.left, rect.bottom),  
68 -// // ];  
69 -// // final List<Offset> edges = [shape[0], shape[1], shape[2], shape[3], shape[0]];  
70 -// //  
71 -// // // Check edge intersection  
72 -// // for (int i = 0; i < edges.length - 1; i++) {  
73 -// // for (int j = 0; j < rectCorners.length; j++) {  
74 -// // final int next = (j + 1) % rectCorners.length;  
75 -// // if (_checkIntersection(  
76 -// // edges[i],  
77 -// // edges[i + 1],  
78 -// // rectCorners[j],  
79 -// // rectCorners[next],  
80 -// // )) {  
81 -// // return true;  
82 -// // }  
83 -// // }  
84 -// // }  
85 -// //  
86 -// // // Check if any rect corner is inside the shape  
87 -// // for (final Offset corner in rectCorners) {  
88 -// // if (_isPointInPolygon(shape, corner)) {  
89 -// // return true;  
90 -// // }  
91 -// // }  
92 -// //  
93 -// // return false;  
94 -// // }  
95 -// //  
96 -// // bool _checkIntersection(Offset p1, Offset p2, Offset p3, Offset p4) {  
97 -// // // Calculate the intersection of two line segments  
98 -// // double s1X;  
99 -// // double s1Y;  
100 -// // double s2X;  
101 -// // double s2Y;  
102 -// // s1X = p2.dx - p1.dx;  
103 -// // s1Y = p2.dy - p1.dy;  
104 -// // s2X = p4.dx - p3.dx;  
105 -// // s2Y = p4.dy - p3.dy;  
106 -// //  
107 -// // double s;  
108 -// // double t;  
109 -// // s = (-s1Y * (p1.dx - p3.dx) + s1X * (p1.dy - p3.dy)) /  
110 -// // (-s2X * s1Y + s1X * s2Y);  
111 -// // t = (s2X * (p1.dy - p3.dy) - s2Y * (p1.dx - p3.dx)) /  
112 -// // (-s2X * s1Y + s1X * s2Y);  
113 -// //  
114 -// // return s >= 0 && s <= 1 && t >= 0 && t <= 1;  
115 -// // }  
116 -// //  
117 -// // bool _isPointInPolygon(List<Offset> polygon, Offset point) {  
118 -// // // Ray-casting algorithm for checking if a point is inside a polygon  
119 -// // bool inside = false;  
120 -// // for (int i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {  
121 -// // if ((polygon[i].dy > point.dy) != (polygon[j].dy > point.dy) &&  
122 -// // (point.dx <  
123 -// // (polygon[j].dx - polygon[i].dx) *  
124 -// // (point.dy - polygon[i].dy) /  
125 -// // (polygon[j].dy - polygon[i].dy) +  
126 -// // polygon[i].dx)) {  
127 -// // inside = !inside;  
128 -// // }  
129 -// // }  
130 -// // return inside;  
131 -// // }  
1 -import 'package:flutter/foundation.dart';  
2 -import 'package:flutter/material.dart';  
3 -  
4 -class BarcodeOverlay extends CustomPainter {  
5 - BarcodeOverlay({  
6 - required this.barcodeCorners,  
7 - required this.barcodeSize,  
8 - required this.boxFit,  
9 - required this.cameraPreviewSize,  
10 - });  
11 -  
12 - final List<Offset> barcodeCorners;  
13 - final Size barcodeSize;  
14 - final BoxFit boxFit;  
15 - final Size cameraPreviewSize;  
16 -  
17 - @override  
18 - void paint(Canvas canvas, Size size) {  
19 - if (barcodeCorners.isEmpty ||  
20 - barcodeSize.isEmpty ||  
21 - cameraPreviewSize.isEmpty) {  
22 - return;  
23 - }  
24 -  
25 - final adjustedSize = applyBoxFit(boxFit, cameraPreviewSize, size);  
26 -  
27 - double verticalPadding = size.height - adjustedSize.destination.height;  
28 - double horizontalPadding = size.width - adjustedSize.destination.width;  
29 - if (verticalPadding > 0) {  
30 - verticalPadding = verticalPadding / 2;  
31 - } else {  
32 - verticalPadding = 0;  
33 - }  
34 -  
35 - if (horizontalPadding > 0) {  
36 - horizontalPadding = horizontalPadding / 2;  
37 - } else {  
38 - horizontalPadding = 0;  
39 - }  
40 -  
41 - final double ratioWidth;  
42 - final double ratioHeight;  
43 -  
44 - if (!kIsWeb && defaultTargetPlatform == TargetPlatform.iOS) {  
45 - ratioWidth = barcodeSize.width / adjustedSize.destination.width;  
46 - ratioHeight = barcodeSize.height / adjustedSize.destination.height;  
47 - } else {  
48 - ratioWidth = cameraPreviewSize.width / adjustedSize.destination.width;  
49 - ratioHeight = cameraPreviewSize.height / adjustedSize.destination.height;  
50 - }  
51 -  
52 - final List<Offset> adjustedOffset = [  
53 - for (final offset in barcodeCorners)  
54 - Offset(  
55 - offset.dx / ratioWidth + horizontalPadding,  
56 - offset.dy / ratioHeight + verticalPadding,  
57 - ),  
58 - ];  
59 -  
60 - final cutoutPath = Path()..addPolygon(adjustedOffset, true);  
61 -  
62 - final backgroundPaint = Paint()  
63 - ..color = Colors.red.withOpacity(1.0)  
64 - ..style = PaintingStyle.fill  
65 - ..blendMode = BlendMode.dstOut;  
66 -  
67 - canvas.drawPath(cutoutPath, backgroundPaint);  
68 - }  
69 -  
70 - @override  
71 - bool shouldRepaint(covariant CustomPainter oldDelegate) {  
72 - return false;  
73 - }  
74 -}  
1 -import 'package:flutter/material.dart';  
2 -import 'package:mobile_scanner/mobile_scanner.dart';  
3 -import 'package:mobile_scanner_example/picklist/widgets/barcode_overlay.dart';  
4 -  
5 -List<Widget> drawDetectedBarcodes({  
6 - required List<Barcode>? barcodes,  
7 - required Size cameraPreviewSize,  
8 - required BoxFit fit,  
9 -}) {  
10 - final barcodeWidgets = <Widget>[];  
11 - if (barcodes == null || barcodes.isEmpty) {  
12 - debugPrint('EMPTY!!!');  
13 - }  
14 - if (barcodes != null) {  
15 - for (final barcode in barcodes) {  
16 - barcodeWidgets.add(  
17 - CustomPaint(  
18 - painter: BarcodeOverlay(  
19 - barcodeCorners: barcode.corners,  
20 - barcodeSize: barcode.size,  
21 - boxFit: fit,  
22 - cameraPreviewSize: cameraPreviewSize,  
23 - ),  
24 - ),  
25 - );  
26 - debugPrint(  
27 - 'barcodeCorners => ${barcode.corners.map((e) => 'x: ${e.dx}, y: ${e.dy} ')}, barcodeSize => width: ${barcode.size.width}, height: ${barcode.size.height}, cameraPreviewSize => width: ${cameraPreviewSize.width}, height: ${cameraPreviewSize.height} ',  
28 - );  
29 - }  
30 - debugPrint(barcodeWidgets.length.toString());  
31 - }  
32 - return barcodeWidgets;  
33 -}