|
|
@ -1,9 +1,7 @@
|
|
|
|
import 'dart:async';
|
|
|
|
import 'dart:io';
|
|
|
|
import 'dart:io' show Platform;
|
|
|
|
|
|
|
|
import 'package:barcode_scan/barcode_scan.dart';
|
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:qr_code_scanner/qr_code_scanner.dart';
|
|
|
|
import 'package:flutter/services.dart';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ScanPage extends StatefulWidget {
|
|
|
|
class ScanPage extends StatefulWidget {
|
|
|
|
ScanPage({Key key}) : super(key: key);
|
|
|
|
ScanPage({Key key}) : super(key: key);
|
|
|
@ -13,263 +11,27 @@ class ScanPage extends StatefulWidget {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class _ScanPageState extends State<ScanPage> {
|
|
|
|
class _ScanPageState extends State<ScanPage> {
|
|
|
|
ScanResult scanResult;
|
|
|
|
final GlobalKey _qrKey = GlobalKey(debugLabel: 'QR');
|
|
|
|
|
|
|
|
QRViewController _controller;
|
|
|
|
final _flashOnController = TextEditingController(text: "Flash on");
|
|
|
|
|
|
|
|
final _flashOffController = TextEditingController(text: "Flash off");
|
|
|
|
|
|
|
|
final _cancelController = TextEditingController(text: "Cancel");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var _aspectTolerance = 0.00;
|
|
|
|
|
|
|
|
var _numberOfCameras = 0;
|
|
|
|
|
|
|
|
var _selectedCamera = -1;
|
|
|
|
|
|
|
|
var _useAutoFocus = true;
|
|
|
|
|
|
|
|
var _autoEnableFlash = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static final _possibleFormats = BarcodeFormat.values.toList()
|
|
|
|
|
|
|
|
..removeWhere((e) => e == BarcodeFormat.unknown);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
List<BarcodeFormat> selectedFormats = [..._possibleFormats];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
|
// ignore: type_annotate_public_apis
|
|
|
|
void reassemble() {
|
|
|
|
initState() {
|
|
|
|
super.reassemble();
|
|
|
|
super.initState();
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
|
|
|
_controller.pauseCamera();
|
|
|
|
Future.delayed(Duration.zero, () async {
|
|
|
|
} else if (Platform.isIOS) {
|
|
|
|
_numberOfCameras = await BarcodeScanner.numberOfCameras;
|
|
|
|
_controller.resumeCamera();
|
|
|
|
setState(() {});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@override
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
var contentList = <Widget>[
|
|
|
|
|
|
|
|
if (scanResult != null)
|
|
|
|
|
|
|
|
Card(
|
|
|
|
|
|
|
|
child: Column(
|
|
|
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Result Type"),
|
|
|
|
|
|
|
|
subtitle: Text(scanResult.type?.toString() ?? ""),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Raw Content"),
|
|
|
|
|
|
|
|
subtitle: Text(scanResult.rawContent ?? ""),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Format"),
|
|
|
|
|
|
|
|
subtitle: Text(scanResult.format?.toString() ?? ""),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Format note"),
|
|
|
|
|
|
|
|
subtitle: Text(scanResult.formatNote ?? ""),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Camera selection"),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
RadioListTile(
|
|
|
|
|
|
|
|
onChanged: (v) => setState(() => _selectedCamera = -1),
|
|
|
|
|
|
|
|
value: -1,
|
|
|
|
|
|
|
|
title: Text("Default camera"),
|
|
|
|
|
|
|
|
groupValue: _selectedCamera,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < _numberOfCameras; i++) {
|
|
|
|
|
|
|
|
contentList.add(RadioListTile(
|
|
|
|
|
|
|
|
onChanged: (v) => setState(() => _selectedCamera = i),
|
|
|
|
|
|
|
|
value: i,
|
|
|
|
|
|
|
|
title: Text("Camera ${i + 1}"),
|
|
|
|
|
|
|
|
groupValue: _selectedCamera,
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contentList.addAll([
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Button Texts"),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: TextField(
|
|
|
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
|
|
|
labelText: "Flash On",
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
controller: _flashOnController,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: TextField(
|
|
|
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
|
|
|
labelText: "Flash Off",
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
controller: _flashOffController,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: TextField(
|
|
|
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
|
|
|
labelText: "Cancel",
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
controller: _cancelController,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Platform.isAndroid) {
|
|
|
|
|
|
|
|
contentList.addAll([
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Android specific options"),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title:
|
|
|
|
|
|
|
|
Text("Aspect tolerance (${_aspectTolerance.toStringAsFixed(2)})"),
|
|
|
|
|
|
|
|
subtitle: Slider(
|
|
|
|
|
|
|
|
min: -1.0,
|
|
|
|
|
|
|
|
max: 1.0,
|
|
|
|
|
|
|
|
value: _aspectTolerance,
|
|
|
|
|
|
|
|
onChanged: (value) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
_aspectTolerance = value;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
CheckboxListTile(
|
|
|
|
|
|
|
|
title: Text("Use autofocus"),
|
|
|
|
|
|
|
|
value: _useAutoFocus,
|
|
|
|
|
|
|
|
onChanged: (checked) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
_useAutoFocus = checked;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contentList.addAll([
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Other options"),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
CheckboxListTile(
|
|
|
|
|
|
|
|
title: Text("Start with flash"),
|
|
|
|
|
|
|
|
value: _autoEnableFlash,
|
|
|
|
|
|
|
|
onChanged: (checked) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
_autoEnableFlash = checked;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contentList.addAll([
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
title: Text("Barcode formats"),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
ListTile(
|
|
|
|
|
|
|
|
trailing: Checkbox(
|
|
|
|
|
|
|
|
tristate: true,
|
|
|
|
|
|
|
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
|
|
|
|
|
|
|
value: selectedFormats.length == _possibleFormats.length
|
|
|
|
|
|
|
|
? true
|
|
|
|
|
|
|
|
: selectedFormats.length == 0
|
|
|
|
|
|
|
|
? false
|
|
|
|
|
|
|
|
: null,
|
|
|
|
|
|
|
|
onChanged: (checked) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
selectedFormats = [
|
|
|
|
|
|
|
|
if (checked ?? false) ..._possibleFormats,
|
|
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
dense: true,
|
|
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
title: Text("Detect barcode formats"),
|
|
|
|
|
|
|
|
subtitle: Text(
|
|
|
|
|
|
|
|
'If all are unselected, all possible platform formats will be used',
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
contentList.addAll(_possibleFormats.map(
|
|
|
|
|
|
|
|
(format) => CheckboxListTile(
|
|
|
|
|
|
|
|
value: selectedFormats.contains(format),
|
|
|
|
|
|
|
|
onChanged: (i) {
|
|
|
|
|
|
|
|
setState(() => selectedFormats.contains(format)
|
|
|
|
|
|
|
|
? selectedFormats.remove(format)
|
|
|
|
|
|
|
|
: selectedFormats.add(format));
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
title: Text(format.toString()),
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Scaffold(
|
|
|
|
return Scaffold(
|
|
|
|
appBar: AppBar(
|
|
|
|
body: QRView(
|
|
|
|
title: Text('Barcode Scanner Example'),
|
|
|
|
key: _qrKey,
|
|
|
|
actions: <Widget>[
|
|
|
|
onQRViewCreated: (controller) {
|
|
|
|
IconButton(
|
|
|
|
_controller = controller;
|
|
|
|
icon: Icon(Icons.camera),
|
|
|
|
},
|
|
|
|
tooltip: "Scan",
|
|
|
|
|
|
|
|
onPressed: scan,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
],
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
body: ListView(
|
|
|
|
|
|
|
|
scrollDirection: Axis.vertical,
|
|
|
|
|
|
|
|
shrinkWrap: true,
|
|
|
|
|
|
|
|
children: contentList,
|
|
|
|
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Future scan() async {
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
var options = ScanOptions(
|
|
|
|
|
|
|
|
strings: {
|
|
|
|
|
|
|
|
"cancel": _cancelController.text,
|
|
|
|
|
|
|
|
"flash_on": _flashOnController.text,
|
|
|
|
|
|
|
|
"flash_off": _flashOffController.text,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
restrictFormat: selectedFormats,
|
|
|
|
|
|
|
|
useCamera: _selectedCamera,
|
|
|
|
|
|
|
|
autoEnableFlash: _autoEnableFlash,
|
|
|
|
|
|
|
|
android: AndroidOptions(
|
|
|
|
|
|
|
|
aspectTolerance: _aspectTolerance,
|
|
|
|
|
|
|
|
useAutoFocus: _useAutoFocus,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var result = await BarcodeScanner.scan(options: options);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setState(() => scanResult = result);
|
|
|
|
|
|
|
|
} on PlatformException catch (e) {
|
|
|
|
|
|
|
|
var result = ScanResult(
|
|
|
|
|
|
|
|
type: ResultType.Error,
|
|
|
|
|
|
|
|
format: BarcodeFormat.unknown,
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (e.code == BarcodeScanner.cameraAccessDenied) {
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
result.rawContent = 'The user did not grant the camera permission!';
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
result.rawContent = 'Unknown error: $e';
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
setState(() {
|
|
|
|
|
|
|
|
scanResult = result;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|