Navaron Bracke

clean up the zoom slider example

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:mobile_scanner_example/scanner_button_widgets.dart';
import 'package:mobile_scanner_example/scanner_error_widget.dart';
class BarcodeScannerWithZoom extends StatefulWidget {
... ... @@ -15,60 +17,51 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom>
with SingleTickerProviderStateMixin {
BarcodeCapture? barcode;
MobileScannerController controller = MobileScannerController(
final MobileScannerController controller = MobileScannerController(
torchEnabled: true,
);
bool isStarted = true;
double _zoomFactor = 0.0;
StreamSubscription<Object?>? _barcodesSubscription;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('With zoom slider')),
backgroundColor: Colors.black,
body: Builder(
builder: (context) {
return Stack(
children: [
MobileScanner(
controller: controller,
fit: BoxFit.contain,
errorBuilder: (context, error, child) {
return ScannerErrorWidget(error: error);
},
onDetect: (barcode) {
void initState() {
super.initState();
_barcodesSubscription = controller.barcodes.listen((event) {
setState(() {
this.barcode = barcode;
barcode = event;
});
},
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Column(
children: [
Padding(
});
controller.start();
}
Widget _buildZoomScaleSlider() {
return ValueListenableBuilder(
valueListenable: controller,
builder: (context, state, child) {
if (!state.isInitialized || !state.isRunning) {
return const SizedBox.shrink();
}
final TextStyle labelStyle = Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(color: Colors.white);
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 8.0),
child: Row(
children: [
Text(
"0%",
'0%',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(color: Colors.white),
style: labelStyle,
),
Expanded(
child: Slider(
max: 100,
divisions: 100,
value: _zoomFactor,
label: "${_zoomFactor.round()} %",
onChanged: (value) {
setState(() {
_zoomFactor = value;
... ... @@ -78,54 +71,47 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom>
),
),
Text(
"100%",
'100%',
overflow: TextOverflow.fade,
style: Theme.of(context)
.textTheme
.headlineMedium!
.copyWith(color: Colors.white),
style: labelStyle,
),
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
IconButton(
color: Colors.white,
icon: ValueListenableBuilder<TorchState>(
valueListenable: controller.torchState,
builder: (context, state, child) {
switch (state) {
case TorchState.off:
return const Icon(
Icons.flash_off,
color: Colors.grey,
);
case TorchState.on:
return const Icon(
Icons.flash_on,
color: Colors.yellow,
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('With zoom slider')),
backgroundColor: Colors.black,
body: Builder(
builder: (context) {
return Stack(
children: [
MobileScanner(
controller: controller,
fit: BoxFit.contain,
errorBuilder: (context, error, child) {
return ScannerErrorWidget(error: error);
},
),
iconSize: 32.0,
onPressed: () => controller.toggleTorch(),
),
IconButton(
color: Colors.white,
icon: isStarted
? const Icon(Icons.stop)
: const Icon(Icons.play_arrow),
iconSize: 32.0,
onPressed: () => setState(() {
isStarted
? controller.stop()
: controller.start();
isStarted = !isStarted;
}),
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
alignment: Alignment.bottomCenter,
height: 100,
color: Colors.black.withOpacity(0.4),
child: Column(
children: [
_buildZoomScaleSlider(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ToggleFlashlightButton(controller: controller),
StartStopMobileScannerButton(controller: controller),
Center(
child: SizedBox(
width: MediaQuery.of(context).size.width - 200,
... ... @@ -143,53 +129,8 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom>
),
),
),
IconButton(
color: Colors.white,
icon: ValueListenableBuilder<CameraFacing>(
valueListenable: controller.cameraFacingState,
builder: (context, state, child) {
switch (state) {
case CameraFacing.front:
return const Icon(Icons.camera_front);
case CameraFacing.back:
return const Icon(Icons.camera_rear);
}
},
),
iconSize: 32.0,
onPressed: () => controller.switchCamera(),
),
IconButton(
color: Colors.white,
icon: const Icon(Icons.image),
iconSize: 32.0,
onPressed: () async {
final ImagePicker picker = ImagePicker();
// Pick an image
final XFile? image = await picker.pickImage(
source: ImageSource.gallery,
);
if (image != null) {
if (await controller.analyzeImage(image.path)) {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Barcode found!'),
backgroundColor: Colors.green,
),
);
} else {
if (!context.mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('No barcode found!'),
backgroundColor: Colors.red,
),
);
}
}
},
),
SwitchCameraButton(controller: controller),
AnalyzeImageFromGalleryButton(controller: controller),
],
),
],
... ... @@ -202,4 +143,11 @@ class _BarcodeScannerWithZoomState extends State<BarcodeScannerWithZoom>
),
);
}
@override
Future<void> dispose() async {
_barcodesSubscription?.cancel();
await controller.dispose();
super.dispose();
}
}
... ...