Ayush Pawar

scanner with overlay screen added

@@ -155,7 +155,7 @@ @@ -155,7 +155,7 @@
155 97C146E61CF9000F007C117D /* Project object */ = { 155 97C146E61CF9000F007C117D /* Project object */ = {
156 isa = PBXProject; 156 isa = PBXProject;
157 attributes = { 157 attributes = {
158 - LastUpgradeCheck = 1300; 158 + LastUpgradeCheck = 1430;
159 ORGANIZATIONNAME = ""; 159 ORGANIZATIONNAME = "";
160 TargetAttributes = { 160 TargetAttributes = {
161 97C146ED1CF9000F007C117D = { 161 97C146ED1CF9000F007C117D = {
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <Scheme 2 <Scheme
3 - LastUpgradeVersion = "1300" 3 + LastUpgradeVersion = "1430"
4 version = "1.3"> 4 version = "1.3">
5 <BuildAction 5 <BuildAction
6 parallelizeBuildables = "YES" 6 parallelizeBuildables = "YES"
@@ -51,5 +51,10 @@ @@ -51,5 +51,10 @@
51 </array> 51 </array>
52 <key>UIViewControllerBasedStatusBarAppearance</key> 52 <key>UIViewControllerBasedStatusBarAppearance</key>
53 <false/> 53 <false/>
  54 + <key>NSCameraUsageDescription</key>
  55 + <string>This app needs camera access to scan QR codes</string>
  56 +
  57 + <key>NSPhotoLibraryUsageDescription</key>
  58 + <string>This app needs photos access to get QR code from photo library</string>
54 </dict> 59 </dict>
55 </plist> 60 </plist>
@@ -6,6 +6,7 @@ import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart'; @@ -6,6 +6,7 @@ import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart';
6 import 'package:mobile_scanner_example/barcode_scanner_window.dart'; 6 import 'package:mobile_scanner_example/barcode_scanner_window.dart';
7 import 'package:mobile_scanner_example/barcode_scanner_without_controller.dart'; 7 import 'package:mobile_scanner_example/barcode_scanner_without_controller.dart';
8 import 'package:mobile_scanner_example/barcode_scanner_zoom.dart'; 8 import 'package:mobile_scanner_example/barcode_scanner_zoom.dart';
  9 +import 'package:mobile_scanner_example/mobile_scanner_overlay.dart';
9 10
10 void main() => runApp(const MaterialApp(home: MyHome())); 11 void main() => runApp(const MaterialApp(home: MyHome()));
11 12
@@ -95,6 +96,16 @@ class MyHome extends StatelessWidget { @@ -95,6 +96,16 @@ class MyHome extends StatelessWidget {
95 }, 96 },
96 child: const Text('MobileScanner pageView'), 97 child: const Text('MobileScanner pageView'),
97 ), 98 ),
  99 + ElevatedButton(
  100 + onPressed: () {
  101 + Navigator.of(context).push(
  102 + MaterialPageRoute(
  103 + builder: (context) => BarcodeScannerWithOverlay(),
  104 + ),
  105 + );
  106 + },
  107 + child: const Text('MobileScanner with Overlay'),
  108 + ),
98 ], 109 ],
99 ), 110 ),
100 ), 111 ),
1 -//TODO: Create example with scanner overlay  
2 1
3 // import 'dart:ui'; 2 // import 'dart:ui';
4 -// 3 +
5 // import 'package:flutter/material.dart'; 4 // import 'package:flutter/material.dart';
6 // import 'package:mobile_scanner/mobile_scanner.dart'; 5 // import 'package:mobile_scanner/mobile_scanner.dart';
7 -// 6 +
8 // void main() { 7 // void main() {
9 // runApp(const AnalyzeView()); 8 // runApp(const AnalyzeView());
10 // } 9 // }
11 -// 10 +
12 // class AnalyzeView extends StatefulWidget { 11 // class AnalyzeView extends StatefulWidget {
13 // const AnalyzeView({Key? key}) : super(key: key); 12 // const AnalyzeView({Key? key}) : super(key: key);
14 -// 13 +
15 // @override 14 // @override
16 // _AnalyzeViewState createState() => _AnalyzeViewState(); 15 // _AnalyzeViewState createState() => _AnalyzeViewState();
17 // } 16 // }
18 -// 17 +
19 // class _AnalyzeViewState extends State<AnalyzeView> 18 // class _AnalyzeViewState extends State<AnalyzeView>
20 // with SingleTickerProviderStateMixin { 19 // with SingleTickerProviderStateMixin {
21 // List<Offset> points = []; 20 // List<Offset> points = [];
22 -// 21 +
23 // // CameraController cameraController = CameraController(context, width: 320, height: 150); 22 // // CameraController cameraController = CameraController(context, width: 320, height: 150);
24 -// 23 +
25 // String? barcode; 24 // String? barcode;
26 -// 25 +
27 // @override 26 // @override
28 // Widget build(BuildContext context) { 27 // Widget build(BuildContext context) {
29 // return MaterialApp( 28 // return MaterialApp(
@@ -34,7 +33,7 @@ @@ -34,7 +33,7 @@
34 // MobileScanner( 33 // MobileScanner(
35 // // fitScreen: false, 34 // // fitScreen: false,
36 // // controller: cameraController, 35 // // controller: cameraController,
37 -// onDetect: (barcode, args) { 36 +// onDetect: (barcode) {
38 // if (this.barcode != barcode.rawValue) { 37 // if (this.barcode != barcode.rawValue) {
39 // this.barcode = barcode.rawValue; 38 // this.barcode = barcode.rawValue;
40 // if (barcode.corners != null) { 39 // if (barcode.corners != null) {
@@ -92,21 +91,21 @@ @@ -92,21 +91,21 @@
92 // ), 91 // ),
93 // ); 92 // );
94 // } 93 // }
95 -// 94 +
96 // @override 95 // @override
97 // void dispose() { 96 // void dispose() {
98 // // cameraController.dispose(); 97 // // cameraController.dispose();
99 // super.dispose(); 98 // super.dispose();
100 // } 99 // }
101 -// 100 +
102 // void display(Barcode barcode) { 101 // void display(Barcode barcode) {
103 // Navigator.of(context).popAndPushNamed('display', arguments: barcode); 102 // Navigator.of(context).popAndPushNamed('display', arguments: barcode);
104 // } 103 // }
105 // } 104 // }
106 -// 105 +
107 // class OpenPainter extends CustomPainter { 106 // class OpenPainter extends CustomPainter {
108 // final List<Offset> points; 107 // final List<Offset> points;
109 -// 108 +
110 // OpenPainter(this.points); 109 // OpenPainter(this.points);
111 // @override 110 // @override
112 // void paint(Canvas canvas, Size size) { 111 // void paint(Canvas canvas, Size size) {
@@ -116,11 +115,11 @@ @@ -116,11 +115,11 @@
116 // //draw points on canvas 115 // //draw points on canvas
117 // canvas.drawPoints(PointMode.points, points, paint1); 116 // canvas.drawPoints(PointMode.points, points, paint1);
118 // } 117 // }
119 -// 118 +
120 // @override 119 // @override
121 // bool shouldRepaint(CustomPainter oldDelegate) => true; 120 // bool shouldRepaint(CustomPainter oldDelegate) => true;
122 // } 121 // }
123 -// 122 +
124 // class OpacityCurve extends Curve { 123 // class OpacityCurve extends Curve {
125 // @override 124 // @override
126 // double transform(double t) { 125 // double transform(double t) {
@@ -133,96 +132,199 @@ @@ -133,96 +132,199 @@
133 // } 132 // }
134 // } 133 // }
135 // } 134 // }
136 -//  
137 -// // import 'package:flutter/material.dart';  
138 -// // import 'package:flutter/rendering.dart';  
139 -// // import 'package:mobile_scanner/mobile_scanner.dart';  
140 -// //  
141 -// // void main() {  
142 -// // debugPaintSizeEnabled = false;  
143 -// // runApp(HomePage());  
144 -// // }  
145 -// //  
146 -// // class HomePage extends StatefulWidget {  
147 -// // @override  
148 -// // HomeState createState() => HomeState();  
149 -// // }  
150 -// //  
151 -// // class HomeState extends State<HomePage> {  
152 -// // @override  
153 -// // Widget build(BuildContext context) {  
154 -// // return MaterialApp(home: MyApp());  
155 -// // }  
156 -// // }  
157 -// //  
158 -// // class MyApp extends StatefulWidget {  
159 -// // @override  
160 -// // _MyAppState createState() => _MyAppState();  
161 -// // }  
162 -// //  
163 -// // class _MyAppState extends State<MyApp> {  
164 -// // String? qr;  
165 -// // bool camState = false;  
166 -// //  
167 -// // @override  
168 -// // initState() {  
169 -// // super.initState();  
170 -// // }  
171 -// //  
172 -// // @override  
173 -// // Widget build(BuildContext context) {  
174 -// // return Scaffold(  
175 -// // appBar: AppBar(  
176 -// // title: Text('Plugin example app'),  
177 -// // ),  
178 -// // body: Center(  
179 -// // child: Column(  
180 -// // crossAxisAlignment: CrossAxisAlignment.center,  
181 -// // mainAxisAlignment: MainAxisAlignment.center,  
182 -// // children: <Widget>[  
183 -// // Expanded(  
184 -// // child: camState  
185 -// // ? Center(  
186 -// // child: SizedBox(  
187 -// // width: 300.0,  
188 -// // height: 600.0,  
189 -// // child: MobileScanner(  
190 -// // onError: (context, error) => Text(  
191 -// // error.toString(),  
192 -// // style: TextStyle(color: Colors.red),  
193 -// // ),  
194 -// // qrCodeCallback: (code) {  
195 -// // setState(() {  
196 -// // qr = code;  
197 -// // });  
198 -// // },  
199 -// // child: Container(  
200 -// // decoration: BoxDecoration(  
201 -// // color: Colors.transparent,  
202 -// // border: Border.all(  
203 -// // color: Colors.orange,  
204 -// // width: 10.0,  
205 -// // style: BorderStyle.solid),  
206 -// // ),  
207 -// // ),  
208 -// // ),  
209 -// // ),  
210 -// // )  
211 -// // : Center(child: Text("Camera inactive"))),  
212 -// // Text("QRCODE: $qr"),  
213 -// // ],  
214 -// // ),  
215 -// // ),  
216 -// // floatingActionButton: FloatingActionButton(  
217 -// // child: Text(  
218 -// // "press me",  
219 -// // textAlign: TextAlign.center,  
220 -// // ),  
221 -// // onPressed: () {  
222 -// // setState(() {  
223 -// // camState = !camState;  
224 -// // });  
225 -// // }),  
226 -// // );  
227 -// // }  
228 -// // } 135 +
  136 +import 'package:flutter/material.dart';
  137 +import 'package:flutter/rendering.dart';
  138 +import 'package:mobile_scanner/mobile_scanner.dart';
  139 +import 'package:mobile_scanner_example/barcode_scanner_window.dart';
  140 +import 'package:mobile_scanner_example/scanner_error_widget.dart';
  141 +
  142 +void main() {
  143 + debugPaintSizeEnabled = false;
  144 + runApp(HomePage());
  145 +}
  146 +
  147 +class HomePage extends StatefulWidget {
  148 + @override
  149 + HomeState createState() => HomeState();
  150 +}
  151 +
  152 +class HomeState extends State<HomePage> {
  153 + @override
  154 + Widget build(BuildContext context) {
  155 + return MaterialApp(home: BarcodeScannerWithOverlay());
  156 + }
  157 +}
  158 +
  159 +class BarcodeScannerWithOverlay extends StatefulWidget {
  160 + @override
  161 + _MyAppState createState() => _MyAppState();
  162 +}
  163 +
  164 +class _MyAppState extends State<BarcodeScannerWithOverlay> {
  165 + String? qr;
  166 + String overlayText = "Please scan QR Code";
  167 + bool camState = false;
  168 + late BarcodeCapture currentBarcodeCapture ;
  169 + final MobileScannerController controller = MobileScannerController(
  170 + facing: CameraFacing.back,
  171 + autoStart: false
  172 + );
  173 + @override
  174 + initState() {
  175 + super.initState();
  176 + }
  177 +
  178 + @override
  179 + dispose() {
  180 + super.dispose();
  181 + controller.dispose();
  182 + }
  183 +
  184 + configureCameraSettings() {
  185 + setState(() {
  186 + camState = !camState;
  187 + controller.start();
  188 + });
  189 + }
  190 +
  191 + onBarcodeDetect(BarcodeCapture barcodeCapture) {
  192 + setState(() {
  193 + currentBarcodeCapture = barcodeCapture;
  194 + overlayText = barcodeCapture.barcodes.last.displayValue!;
  195 + });
  196 + }
  197 +
  198 +
  199 +
  200 + @override
  201 + Widget build(BuildContext context) {
  202 + final scanWindow = Rect.fromCenter(
  203 + center: MediaQuery.of(context).size.center(Offset.zero),
  204 + width: 200,
  205 + height: 200,
  206 + );
  207 + final height = MediaQuery.of(context).size.height;
  208 + final width = MediaQuery.of(context).size.width;
  209 + return Scaffold(
  210 + appBar: AppBar(
  211 + title: const Text('Scanner with Overlay Example app'),
  212 + ),
  213 + body: Center(
  214 + child: Column(
  215 + crossAxisAlignment: CrossAxisAlignment.center,
  216 + mainAxisAlignment: MainAxisAlignment.center,
  217 + children: <Widget>[
  218 + Expanded(
  219 + child: camState
  220 + ? Stack(
  221 + fit: StackFit.expand,
  222 + children: [
  223 + Center(
  224 + child: MobileScanner(
  225 + fit: BoxFit.contain,
  226 + onDetect: (BarcodeCapture barcodeCapture) => {
  227 + onBarcodeDetect(barcodeCapture)
  228 +
  229 + },
  230 + overlay:
  231 + Positioned(
  232 + bottom: height * 0.2,
  233 + child:Opacity(opacity: 0.7, child:
  234 + Text(overlayText, style: const TextStyle(backgroundColor: Colors.black26, color: Colors.white, fontWeight: FontWeight.bold, fontSize: 24, overflow: TextOverflow.ellipsis,),
  235 + maxLines: 1,
  236 + )
  237 + ) ,
  238 + ),
  239 +
  240 + controller: controller,
  241 + scanWindow: scanWindow,
  242 + errorBuilder: (context, error, child) {
  243 + return ScannerErrorWidget(error: error);
  244 + },
  245 + ),
  246 +
  247 + ),
  248 + CustomPaint(
  249 + painter: ScannerOverlay(scanWindow),
  250 + ),
  251 + Positioned(
  252 + bottom: 0.07 * height,
  253 + left: 0.35 * width,
  254 + child: Row(
  255 + mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  256 + children: [
  257 + IconButton(onPressed: ()=>{
  258 + controller.toggleTorch()
  259 + }, icon: const Icon(Icons.flashlight_on, color: Colors.white,),),
  260 + IconButton(onPressed: ()=>{
  261 + controller.switchCamera()
  262 + }, icon: const Icon(Icons.cameraswitch_rounded, color: Colors.white,)),
  263 + ],
  264 + ),
  265 + )
  266 + ],
  267 + )
  268 + : const Center(child: Text("Tap on Camera to activate QR Scanner"))),
  269 +
  270 + ],
  271 + ),
  272 + ),
  273 + floatingActionButton: camState ? null : FloatingActionButton(
  274 + child: Icon(
  275 + Icons.camera_alt
  276 + ),
  277 + onPressed: () {
  278 + configureCameraSettings();
  279 + }),
  280 + );
  281 + }
  282 +}
  283 +
  284 +class ScannerOverlay extends CustomPainter {
  285 + ScannerOverlay(this.scanWindow);
  286 +
  287 + final Rect scanWindow;
  288 +
  289 + @override
  290 + void paint(Canvas canvas, Size size) {
  291 + final backgroundPath = Path()..addRect(Rect.largest);
  292 + final cutoutPath = Path()..addRect(scanWindow);
  293 +
  294 + final backgroundPaint = Paint()
  295 + ..color = Colors.black.withOpacity(0.5)
  296 + ..style = PaintingStyle.fill
  297 + ..blendMode = BlendMode.dstOut;
  298 +
  299 + final backgroundWithCutout = Path.combine(
  300 + PathOperation.difference,
  301 + backgroundPath,
  302 + cutoutPath,
  303 + );
  304 +
  305 + // Create a Paint object for the white border
  306 + final borderPaint = Paint()
  307 + ..color = Colors.white
  308 + ..style = PaintingStyle.stroke
  309 + ..strokeWidth = 4.0; // Adjust the border width as needed
  310 +
  311 + // Calculate the border rectangle with rounded corners
  312 + final borderRadius = BorderRadius.circular(12.0); // Adjust the radius as needed
  313 + final borderRect = RRect.fromRectAndCorners(
  314 + scanWindow,
  315 + topLeft: Radius.circular(12.0),
  316 + topRight: Radius.circular(12.0),
  317 + bottomLeft: Radius.circular(12.0),
  318 + bottomRight: Radius.circular(12.0),
  319 + );
  320 +
  321 + // Draw the white border
  322 + canvas.drawPath(backgroundWithCutout, backgroundPaint);
  323 + canvas.drawRRect(borderRect, borderPaint);
  324 + }
  325 +
  326 + @override
  327 + bool shouldRepaint(covariant CustomPainter oldDelegate) {
  328 + return false;
  329 + }
  330 +}
@@ -202,7 +202,7 @@ @@ -202,7 +202,7 @@
202 isa = PBXProject; 202 isa = PBXProject;
203 attributes = { 203 attributes = {
204 LastSwiftUpdateCheck = 0920; 204 LastSwiftUpdateCheck = 0920;
205 - LastUpgradeCheck = 1300; 205 + LastUpgradeCheck = 1430;
206 ORGANIZATIONNAME = ""; 206 ORGANIZATIONNAME = "";
207 TargetAttributes = { 207 TargetAttributes = {
208 33CC10EC2044A3C60003C045 = { 208 33CC10EC2044A3C60003C045 = {
1 <?xml version="1.0" encoding="UTF-8"?> 1 <?xml version="1.0" encoding="UTF-8"?>
2 <Scheme 2 <Scheme
3 - LastUpgradeVersion = "1300" 3 + LastUpgradeVersion = "1430"
4 version = "1.3"> 4 version = "1.3">
5 <BuildAction 5 <BuildAction
6 parallelizeBuildables = "YES" 6 parallelizeBuildables = "YES"