Navaron Bracke

fix the barcode scanner controller example

  1 +import 'dart:async';
  2 +
1 import 'package:flutter/material.dart'; 3 import 'package:flutter/material.dart';
2 -import 'package:image_picker/image_picker.dart';  
3 import 'package:mobile_scanner/mobile_scanner.dart'; 4 import 'package:mobile_scanner/mobile_scanner.dart';
  5 +import 'package:mobile_scanner_example/scanner_button_widgets.dart';
4 import 'package:mobile_scanner_example/scanner_error_widget.dart'; 6 import 'package:mobile_scanner_example/scanner_error_widget.dart';
5 7
6 class BarcodeScannerWithController extends StatefulWidget { 8 class BarcodeScannerWithController extends StatefulWidget {
@@ -25,29 +27,23 @@ class _BarcodeScannerWithControllerState @@ -25,29 +27,23 @@ class _BarcodeScannerWithControllerState
25 // returnImage: false, 27 // returnImage: false,
26 ); 28 );
27 29
28 - bool isStarted = true; 30 + StreamSubscription<Object?>? _barcodesSubscription;
29 31
30 - void _startOrStop() {  
31 - try {  
32 - if (isStarted) {  
33 - controller.stop();  
34 - } else {  
35 - controller.start(); 32 + @override
  33 + void initState() {
  34 + super.initState();
  35 + _barcodesSubscription = controller.barcodes.listen((event) {
  36 + if (!context.mounted) {
  37 + return;
36 } 38 }
  39 +
37 setState(() { 40 setState(() {
38 - isStarted = !isStarted; 41 + barcode = event;
  42 + });
39 }); 43 });
40 - } on Exception catch (e) {  
41 - ScaffoldMessenger.of(context).showSnackBar(  
42 - SnackBar(  
43 - content: Text('Something went wrong! $e'),  
44 - backgroundColor: Colors.red,  
45 - ),  
46 - );  
47 - }  
48 - }  
49 44
50 - int? numberOfCameras; 45 + controller.start();
  46 + }
51 47
52 @override 48 @override
53 Widget build(BuildContext context) { 49 Widget build(BuildContext context) {
@@ -59,22 +55,11 @@ class _BarcodeScannerWithControllerState @@ -59,22 +55,11 @@ class _BarcodeScannerWithControllerState
59 return Stack( 55 return Stack(
60 children: [ 56 children: [
61 MobileScanner( 57 MobileScanner(
62 - onScannerStarted: (arguments) {  
63 - if (mounted && arguments?.numberOfCameras != null) {  
64 - numberOfCameras = arguments!.numberOfCameras;  
65 - setState(() {});  
66 - }  
67 - },  
68 controller: controller, 58 controller: controller,
69 errorBuilder: (context, error, child) { 59 errorBuilder: (context, error, child) {
70 return ScannerErrorWidget(error: error); 60 return ScannerErrorWidget(error: error);
71 }, 61 },
72 fit: BoxFit.contain, 62 fit: BoxFit.contain,
73 - onDetect: (barcode) {  
74 - setState(() {  
75 - this.barcode = barcode;  
76 - });  
77 - },  
78 ), 63 ),
79 Align( 64 Align(
80 alignment: Alignment.bottomCenter, 65 alignment: Alignment.bottomCenter,
@@ -85,44 +70,8 @@ class _BarcodeScannerWithControllerState @@ -85,44 +70,8 @@ class _BarcodeScannerWithControllerState
85 child: Row( 70 child: Row(
86 mainAxisAlignment: MainAxisAlignment.spaceEvenly, 71 mainAxisAlignment: MainAxisAlignment.spaceEvenly,
87 children: [ 72 children: [
88 - ValueListenableBuilder(  
89 - valueListenable: controller.hasTorchState,  
90 - builder: (context, state, child) {  
91 - if (state != true) {  
92 - return const SizedBox.shrink();  
93 - }  
94 - return IconButton(  
95 - color: Colors.white,  
96 - icon: ValueListenableBuilder<TorchState>(  
97 - valueListenable: controller.torchState,  
98 - builder: (context, state, child) {  
99 - switch (state) {  
100 - case TorchState.off:  
101 - return const Icon(  
102 - Icons.flash_off,  
103 - color: Colors.grey,  
104 - );  
105 - case TorchState.on:  
106 - return const Icon(  
107 - Icons.flash_on,  
108 - color: Colors.yellow,  
109 - );  
110 - }  
111 - },  
112 - ),  
113 - iconSize: 32.0,  
114 - onPressed: () => controller.toggleTorch(),  
115 - );  
116 - },  
117 - ),  
118 - IconButton(  
119 - color: Colors.white,  
120 - icon: isStarted  
121 - ? const Icon(Icons.stop)  
122 - : const Icon(Icons.play_arrow),  
123 - iconSize: 32.0,  
124 - onPressed: _startOrStop,  
125 - ), 73 + ToggleFlashlightButton(controller: controller),
  74 + StartStopMobileScannerButton(controller: controller),
126 Center( 75 Center(
127 child: SizedBox( 76 child: SizedBox(
128 width: MediaQuery.of(context).size.width - 200, 77 width: MediaQuery.of(context).size.width - 200,
@@ -140,55 +89,8 @@ class _BarcodeScannerWithControllerState @@ -140,55 +89,8 @@ class _BarcodeScannerWithControllerState
140 ), 89 ),
141 ), 90 ),
142 ), 91 ),
143 - IconButton(  
144 - color: Colors.white,  
145 - icon: ValueListenableBuilder<CameraFacing>(  
146 - valueListenable: controller.cameraFacingState,  
147 - builder: (context, state, child) {  
148 - switch (state) {  
149 - case CameraFacing.front:  
150 - return const Icon(Icons.camera_front);  
151 - case CameraFacing.back:  
152 - return const Icon(Icons.camera_rear);  
153 - }  
154 - },  
155 - ),  
156 - iconSize: 32.0,  
157 - onPressed: (numberOfCameras ?? 0) < 2  
158 - ? null  
159 - : () => controller.switchCamera(),  
160 - ),  
161 - IconButton(  
162 - color: Colors.white,  
163 - icon: const Icon(Icons.image),  
164 - iconSize: 32.0,  
165 - onPressed: () async {  
166 - final ImagePicker picker = ImagePicker();  
167 - // Pick an image  
168 - final XFile? image = await picker.pickImage(  
169 - source: ImageSource.gallery,  
170 - );  
171 - if (image != null) {  
172 - if (await controller.analyzeImage(image.path)) {  
173 - if (!context.mounted) return;  
174 - ScaffoldMessenger.of(context).showSnackBar(  
175 - const SnackBar(  
176 - content: Text('Barcode found!'),  
177 - backgroundColor: Colors.green,  
178 - ),  
179 - );  
180 - } else {  
181 - if (!context.mounted) return;  
182 - ScaffoldMessenger.of(context).showSnackBar(  
183 - const SnackBar(  
184 - content: Text('No barcode found!'),  
185 - backgroundColor: Colors.red,  
186 - ),  
187 - );  
188 - }  
189 - }  
190 - },  
191 - ), 92 + SwitchCameraButton(controller: controller),
  93 + AnalyzeImageFromGalleryButton(controller: controller),
192 ], 94 ],
193 ), 95 ),
194 ), 96 ),
@@ -199,4 +101,11 @@ class _BarcodeScannerWithControllerState @@ -199,4 +101,11 @@ class _BarcodeScannerWithControllerState
199 ), 101 ),
200 ); 102 );
201 } 103 }
  104 +
  105 + @override
  106 + Future<void> dispose() async {
  107 + _barcodesSubscription?.cancel();
  108 + await controller.dispose();
  109 + super.dispose();
  110 + }
202 } 111 }