refactor: revert autoStart and onDetect. See changelog for more
Showing
8 changed files
with
148 additions
and
9 deletions
| 1 | +## 5.1.0 | ||
| 2 | + | ||
| 3 | +This updates reverts a few breaking changes made in v5.0.0 in order to keep things simple. | ||
| 4 | + | ||
| 5 | +* The `onDetect` method has been reinstated in the `MobileScanner` widget, but is nullable. You can | ||
| 6 | +still listen to `MobileScannerController.barcodes` directly by passing null to this parameter. | ||
| 7 | +* The `autoStart` attribute has been reinstated in the `MobileScannerController` and defaults to true. However, if you want | ||
| 8 | +to control which camera is used on start, or you want to manage the lifecycle yourself, you should set | ||
| 9 | +autoStart to false and manually call `MobileScannerController.start({CameraFacing? cameraDirection})`. | ||
| 10 | +* The `controller` is no longer required in the `MobileScanner` widget. However if provided, the user should take care | ||
| 11 | +of disposing it. | ||
| 12 | +* [Android] Revert Gradle 8 back to Gradle 7, to be inline with most Flutter plugins and prevent build issues. | ||
| 13 | +* [Android] Revert Kotlin back from 1.9 to 1.7 to be inline with most Flutter plugins. Special 1.9 functionality | ||
| 14 | +has been refactored to be compatible with 1.7. | ||
| 15 | + | ||
| 16 | + | ||
| 1 | ## 5.0.2 | 17 | ## 5.0.2 |
| 2 | 18 | ||
| 3 | Bugs fixed: | 19 | Bugs fixed: |
| @@ -7,6 +7,10 @@ | @@ -7,6 +7,10 @@ | ||
| 7 | 7 | ||
| 8 | A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS. | 8 | A universal scanner for Flutter based on MLKit. Uses CameraX on Android and AVFoundation on iOS. |
| 9 | 9 | ||
| 10 | +## Breaking Changes V5.0.0 | ||
| 11 | + | ||
| 12 | +Version 5.0.0 brings some breaking changes. Please see the changelog for an overview. | ||
| 13 | + | ||
| 10 | ## Features Supported | 14 | ## Features Supported |
| 11 | 15 | ||
| 12 | See the example app for detailed implementation information. | 16 | See the example app for detailed implementation information. |
| @@ -13,7 +13,8 @@ class BarcodeScannerPageView extends StatefulWidget { | @@ -13,7 +13,8 @@ class BarcodeScannerPageView extends StatefulWidget { | ||
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | class _BarcodeScannerPageViewState extends State<BarcodeScannerPageView> { | 15 | class _BarcodeScannerPageViewState extends State<BarcodeScannerPageView> { |
| 16 | - final MobileScannerController controller = MobileScannerController(); | 16 | + final MobileScannerController controller = |
| 17 | + MobileScannerController(autoStart: false); | ||
| 17 | 18 | ||
| 18 | final PageController pageController = PageController(); | 19 | final PageController pageController = PageController(); |
| 19 | 20 |
example/lib/barcode_scanner_simple.dart
0 → 100644
| 1 | +import 'dart:async'; | ||
| 2 | + | ||
| 3 | +import 'package:flutter/material.dart'; | ||
| 4 | +import 'package:mobile_scanner/mobile_scanner.dart'; | ||
| 5 | +import 'package:mobile_scanner_example/scanner_button_widgets.dart'; | ||
| 6 | +import 'package:mobile_scanner_example/scanner_error_widget.dart'; | ||
| 7 | + | ||
| 8 | +class BarcodeScannerSimple extends StatefulWidget { | ||
| 9 | + const BarcodeScannerSimple({super.key}); | ||
| 10 | + | ||
| 11 | + @override | ||
| 12 | + State<BarcodeScannerSimple> createState() => _BarcodeScannerSimpleState(); | ||
| 13 | +} | ||
| 14 | + | ||
| 15 | +class _BarcodeScannerSimpleState extends State<BarcodeScannerSimple> { | ||
| 16 | + Barcode? _barcode; | ||
| 17 | + | ||
| 18 | + Widget _buildBarcode(Barcode? value) { | ||
| 19 | + if (value == null) { | ||
| 20 | + return const Text( | ||
| 21 | + 'Scan something!', | ||
| 22 | + overflow: TextOverflow.fade, | ||
| 23 | + style: TextStyle(color: Colors.white), | ||
| 24 | + ); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + return Text( | ||
| 28 | + value.displayValue ?? 'No display value.', | ||
| 29 | + overflow: TextOverflow.fade, | ||
| 30 | + style: const TextStyle(color: Colors.white), | ||
| 31 | + ); | ||
| 32 | + } | ||
| 33 | + | ||
| 34 | + void _handleBarcode(BarcodeCapture barcodes) { | ||
| 35 | + if (mounted) { | ||
| 36 | + setState(() { | ||
| 37 | + _barcode = barcodes.barcodes.firstOrNull; | ||
| 38 | + }); | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + | ||
| 42 | + @override | ||
| 43 | + Widget build(BuildContext context) { | ||
| 44 | + return Scaffold( | ||
| 45 | + appBar: AppBar(title: const Text('Simple scanner')), | ||
| 46 | + backgroundColor: Colors.black, | ||
| 47 | + body: Stack( | ||
| 48 | + children: [ | ||
| 49 | + MobileScanner( | ||
| 50 | + onDetect: _handleBarcode, | ||
| 51 | + ), | ||
| 52 | + Align( | ||
| 53 | + alignment: Alignment.bottomCenter, | ||
| 54 | + child: Container( | ||
| 55 | + alignment: Alignment.bottomCenter, | ||
| 56 | + height: 100, | ||
| 57 | + color: Colors.black.withOpacity(0.4), | ||
| 58 | + child: Row( | ||
| 59 | + mainAxisAlignment: MainAxisAlignment.spaceEvenly, | ||
| 60 | + children: [ | ||
| 61 | + Expanded(child: Center(child: _buildBarcode(_barcode))), | ||
| 62 | + ], | ||
| 63 | + ), | ||
| 64 | + ), | ||
| 65 | + ), | ||
| 66 | + ], | ||
| 67 | + ), | ||
| 68 | + ); | ||
| 69 | + } | ||
| 70 | +} |
| @@ -3,6 +3,7 @@ import 'package:mobile_scanner_example/barcode_scanner_controller.dart'; | @@ -3,6 +3,7 @@ import 'package:mobile_scanner_example/barcode_scanner_controller.dart'; | ||
| 3 | import 'package:mobile_scanner_example/barcode_scanner_listview.dart'; | 3 | import 'package:mobile_scanner_example/barcode_scanner_listview.dart'; |
| 4 | import 'package:mobile_scanner_example/barcode_scanner_pageview.dart'; | 4 | import 'package:mobile_scanner_example/barcode_scanner_pageview.dart'; |
| 5 | import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart'; | 5 | import 'package:mobile_scanner_example/barcode_scanner_returning_image.dart'; |
| 6 | +import 'package:mobile_scanner_example/barcode_scanner_simple.dart'; | ||
| 6 | import 'package:mobile_scanner_example/barcode_scanner_window.dart'; | 7 | import 'package:mobile_scanner_example/barcode_scanner_window.dart'; |
| 7 | import 'package:mobile_scanner_example/barcode_scanner_zoom.dart'; | 8 | import 'package:mobile_scanner_example/barcode_scanner_zoom.dart'; |
| 8 | import 'package:mobile_scanner_example/mobile_scanner_overlay.dart'; | 9 | import 'package:mobile_scanner_example/mobile_scanner_overlay.dart'; |
| @@ -31,6 +32,16 @@ class MyHome extends StatelessWidget { | @@ -31,6 +32,16 @@ class MyHome extends StatelessWidget { | ||
| 31 | onPressed: () { | 32 | onPressed: () { |
| 32 | Navigator.of(context).push( | 33 | Navigator.of(context).push( |
| 33 | MaterialPageRoute( | 34 | MaterialPageRoute( |
| 35 | + builder: (context) => const BarcodeScannerSimple(), | ||
| 36 | + ), | ||
| 37 | + ); | ||
| 38 | + }, | ||
| 39 | + child: const Text('MobileScanner Simple'), | ||
| 40 | + ), | ||
| 41 | + ElevatedButton( | ||
| 42 | + onPressed: () { | ||
| 43 | + Navigator.of(context).push( | ||
| 44 | + MaterialPageRoute( | ||
| 34 | builder: (context) => const BarcodeScannerListView(), | 45 | builder: (context) => const BarcodeScannerListView(), |
| 35 | ), | 46 | ), |
| 36 | ); | 47 | ); |
| @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; | @@ -4,6 +4,7 @@ import 'package:flutter/material.dart'; | ||
| 4 | import 'package:mobile_scanner/src/mobile_scanner_controller.dart'; | 4 | import 'package:mobile_scanner/src/mobile_scanner_controller.dart'; |
| 5 | import 'package:mobile_scanner/src/mobile_scanner_exception.dart'; | 5 | import 'package:mobile_scanner/src/mobile_scanner_exception.dart'; |
| 6 | import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart'; | 6 | import 'package:mobile_scanner/src/mobile_scanner_platform_interface.dart'; |
| 7 | +import 'package:mobile_scanner/src/objects/barcode_capture.dart'; | ||
| 7 | import 'package:mobile_scanner/src/objects/mobile_scanner_state.dart'; | 8 | import 'package:mobile_scanner/src/objects/mobile_scanner_state.dart'; |
| 8 | import 'package:mobile_scanner/src/scan_window_calculation.dart'; | 9 | import 'package:mobile_scanner/src/scan_window_calculation.dart'; |
| 9 | 10 | ||
| @@ -18,7 +19,8 @@ typedef MobileScannerErrorBuilder = Widget Function( | @@ -18,7 +19,8 @@ typedef MobileScannerErrorBuilder = Widget Function( | ||
| 18 | class MobileScanner extends StatefulWidget { | 19 | class MobileScanner extends StatefulWidget { |
| 19 | /// Create a new [MobileScanner] using the provided [controller]. | 20 | /// Create a new [MobileScanner] using the provided [controller]. |
| 20 | const MobileScanner({ | 21 | const MobileScanner({ |
| 21 | - required this.controller, | 22 | + this.controller, |
| 23 | + this.onDetect, | ||
| 22 | this.fit = BoxFit.cover, | 24 | this.fit = BoxFit.cover, |
| 23 | this.errorBuilder, | 25 | this.errorBuilder, |
| 24 | this.overlayBuilder, | 26 | this.overlayBuilder, |
| @@ -29,7 +31,11 @@ class MobileScanner extends StatefulWidget { | @@ -29,7 +31,11 @@ class MobileScanner extends StatefulWidget { | ||
| 29 | }); | 31 | }); |
| 30 | 32 | ||
| 31 | /// The controller for the camera preview. | 33 | /// The controller for the camera preview. |
| 32 | - final MobileScannerController controller; | 34 | + final MobileScannerController? controller; |
| 35 | + | ||
| 36 | + /// The function that signals when new codes were detected by the [controller]. | ||
| 37 | + /// If null, use the contrller.barcodes stream directly to capture barcodes. | ||
| 38 | + final void Function(BarcodeCapture barcodes)? onDetect; | ||
| 33 | 39 | ||
| 34 | /// The error builder for the camera preview. | 40 | /// The error builder for the camera preview. |
| 35 | /// | 41 | /// |
| @@ -113,6 +119,7 @@ class MobileScanner extends StatefulWidget { | @@ -113,6 +119,7 @@ class MobileScanner extends StatefulWidget { | ||
| 113 | } | 119 | } |
| 114 | 120 | ||
| 115 | class _MobileScannerState extends State<MobileScanner> { | 121 | class _MobileScannerState extends State<MobileScanner> { |
| 122 | + late final controller = widget.controller ?? MobileScannerController(); | ||
| 116 | /// The current scan window. | 123 | /// The current scan window. |
| 117 | Rect? scanWindow; | 124 | Rect? scanWindow; |
| 118 | 125 | ||
| @@ -139,7 +146,7 @@ class _MobileScannerState extends State<MobileScanner> { | @@ -139,7 +146,7 @@ class _MobileScannerState extends State<MobileScanner> { | ||
| 139 | if (scanWindow == null) { | 146 | if (scanWindow == null) { |
| 140 | scanWindow = newScanWindow; | 147 | scanWindow = newScanWindow; |
| 141 | 148 | ||
| 142 | - unawaited(widget.controller.updateScanWindow(scanWindow)); | 149 | + unawaited(controller.updateScanWindow(scanWindow)); |
| 143 | 150 | ||
| 144 | return; | 151 | return; |
| 145 | } | 152 | } |
| @@ -154,7 +161,7 @@ class _MobileScannerState extends State<MobileScanner> { | @@ -154,7 +161,7 @@ class _MobileScannerState extends State<MobileScanner> { | ||
| 154 | if (widget.scanWindowUpdateThreshold == 0.0) { | 161 | if (widget.scanWindowUpdateThreshold == 0.0) { |
| 155 | scanWindow = newScanWindow; | 162 | scanWindow = newScanWindow; |
| 156 | 163 | ||
| 157 | - unawaited(widget.controller.updateScanWindow(scanWindow)); | 164 | + unawaited(controller.updateScanWindow(scanWindow)); |
| 158 | 165 | ||
| 159 | return; | 166 | return; |
| 160 | } | 167 | } |
| @@ -167,14 +174,14 @@ class _MobileScannerState extends State<MobileScanner> { | @@ -167,14 +174,14 @@ class _MobileScannerState extends State<MobileScanner> { | ||
| 167 | dy >= widget.scanWindowUpdateThreshold) { | 174 | dy >= widget.scanWindowUpdateThreshold) { |
| 168 | scanWindow = newScanWindow; | 175 | scanWindow = newScanWindow; |
| 169 | 176 | ||
| 170 | - unawaited(widget.controller.updateScanWindow(scanWindow)); | 177 | + unawaited(controller.updateScanWindow(scanWindow)); |
| 171 | } | 178 | } |
| 172 | } | 179 | } |
| 173 | 180 | ||
| 174 | @override | 181 | @override |
| 175 | Widget build(BuildContext context) { | 182 | Widget build(BuildContext context) { |
| 176 | return ValueListenableBuilder<MobileScannerState>( | 183 | return ValueListenableBuilder<MobileScannerState>( |
| 177 | - valueListenable: widget.controller, | 184 | + valueListenable: controller, |
| 178 | builder: (BuildContext context, MobileScannerState value, Widget? child) { | 185 | builder: (BuildContext context, MobileScannerState value, Widget? child) { |
| 179 | if (!value.isInitialized) { | 186 | if (!value.isInitialized) { |
| 180 | const Widget defaultPlaceholder = ColoredBox(color: Colors.black); | 187 | const Widget defaultPlaceholder = ColoredBox(color: Colors.black); |
| @@ -234,10 +241,36 @@ class _MobileScannerState extends State<MobileScanner> { | @@ -234,10 +241,36 @@ class _MobileScannerState extends State<MobileScanner> { | ||
| 234 | ); | 241 | ); |
| 235 | } | 242 | } |
| 236 | 243 | ||
| 244 | + StreamSubscription? barcodeSubscription; | ||
| 245 | + | ||
| 246 | + @override | ||
| 247 | + void initState() { | ||
| 248 | + if (widget.onDetect != null) { | ||
| 249 | + barcodeSubscription = controller.barcodes.listen(widget.onDetect); | ||
| 250 | + } | ||
| 251 | + if (controller.autoStart) { | ||
| 252 | + controller.start(); | ||
| 253 | + } | ||
| 254 | + super.initState(); | ||
| 255 | + } | ||
| 256 | + | ||
| 237 | @override | 257 | @override |
| 238 | void dispose() { | 258 | void dispose() { |
| 239 | super.dispose(); | 259 | super.dispose(); |
| 260 | + if (barcodeSubscription != null) { | ||
| 261 | + barcodeSubscription!.cancel(); | ||
| 262 | + barcodeSubscription = null; | ||
| 263 | + } | ||
| 264 | + | ||
| 265 | + if (controller.autoStart) { | ||
| 266 | + controller.stop(); | ||
| 267 | + } | ||
| 240 | // When this widget is unmounted, reset the scan window. | 268 | // When this widget is unmounted, reset the scan window. |
| 241 | - unawaited(widget.controller.updateScanWindow(null)); | 269 | + unawaited(controller.updateScanWindow(null)); |
| 270 | + | ||
| 271 | + // Dispose default controller if not provided by user | ||
| 272 | + if (widget.controller == null) { | ||
| 273 | + controller.dispose(); | ||
| 274 | + } | ||
| 242 | } | 275 | } |
| 243 | } | 276 | } |
| @@ -17,6 +17,7 @@ import 'package:mobile_scanner/src/objects/start_options.dart'; | @@ -17,6 +17,7 @@ import 'package:mobile_scanner/src/objects/start_options.dart'; | ||
| 17 | class MobileScannerController extends ValueNotifier<MobileScannerState> { | 17 | class MobileScannerController extends ValueNotifier<MobileScannerState> { |
| 18 | /// Construct a new [MobileScannerController] instance. | 18 | /// Construct a new [MobileScannerController] instance. |
| 19 | MobileScannerController({ | 19 | MobileScannerController({ |
| 20 | + this.autoStart = true, | ||
| 20 | this.cameraResolution, | 21 | this.cameraResolution, |
| 21 | this.detectionSpeed = DetectionSpeed.normal, | 22 | this.detectionSpeed = DetectionSpeed.normal, |
| 22 | int detectionTimeoutMs = 250, | 23 | int detectionTimeoutMs = 250, |
| @@ -47,6 +48,9 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { | @@ -47,6 +48,9 @@ class MobileScannerController extends ValueNotifier<MobileScannerState> { | ||
| 47 | /// Currently only supported on Android. | 48 | /// Currently only supported on Android. |
| 48 | final Size? cameraResolution; | 49 | final Size? cameraResolution; |
| 49 | 50 | ||
| 51 | + /// Automatically start the scanner on initialization. | ||
| 52 | + final bool autoStart; | ||
| 53 | + | ||
| 50 | /// The detection speed for the scanner. | 54 | /// The detection speed for the scanner. |
| 51 | /// | 55 | /// |
| 52 | /// Defaults to [DetectionSpeed.normal]. | 56 | /// Defaults to [DetectionSpeed.normal]. |
| 1 | name: mobile_scanner | 1 | name: mobile_scanner |
| 2 | description: A universal barcode and QR code scanner for Flutter based on MLKit. Uses CameraX on Android, AVFoundation on iOS and Apple Vision & AVFoundation on macOS. | 2 | description: A universal barcode and QR code scanner for Flutter based on MLKit. Uses CameraX on Android, AVFoundation on iOS and Apple Vision & AVFoundation on macOS. |
| 3 | -version: 5.0.2 | 3 | +version: 5.1.0 |
| 4 | repository: https://github.com/juliansteenbakker/mobile_scanner | 4 | repository: https://github.com/juliansteenbakker/mobile_scanner |
| 5 | 5 | ||
| 6 | screenshots: | 6 | screenshots: |
-
Please register or login to post a comment