Showing
7 changed files
with
231 additions
and
113 deletions
| @@ -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 = { |
| @@ -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 = { |
-
Please register or login to post a comment