You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
7.2 KiB
277 lines
7.2 KiB
4 years ago
|
import 'dart:async';
|
||
|
import 'dart:io' show Platform;
|
||
|
import 'package:barcode_scan/barcode_scan.dart';
|
||
|
import 'package:flutter/material.dart';
|
||
|
import 'package:flutter/cupertino.dart';
|
||
|
import 'package:flutter/services.dart';
|
||
|
|
||
|
class ScanPage extends StatefulWidget {
|
||
|
ScanPage({Key key}) : super(key: key);
|
||
|
|
||
|
@override
|
||
|
_ScanPageState createState() => _ScanPageState();
|
||
|
}
|
||
|
|
||
|
class _ScanPageState extends State<ScanPage> {
|
||
|
ScanResult scanResult;
|
||
|
|
||
|
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
|
||
|
// ignore: type_annotate_public_apis
|
||
|
initState() {
|
||
|
super.initState();
|
||
|
|
||
|
Future.delayed(Duration.zero, () async {
|
||
|
_numberOfCameras = await BarcodeScanner.numberOfCameras;
|
||
|
setState(() {});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
@override
|
||
|
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(
|
||
|
hasFloatingPlaceholder: true,
|
||
|
labelText: "Flash On",
|
||
|
),
|
||
|
controller: _flashOnController,
|
||
|
),
|
||
|
),
|
||
|
ListTile(
|
||
|
title: TextField(
|
||
|
decoration: InputDecoration(
|
||
|
hasFloatingPlaceholder: true,
|
||
|
labelText: "Flash Off",
|
||
|
),
|
||
|
controller: _flashOffController,
|
||
|
),
|
||
|
),
|
||
|
ListTile(
|
||
|
title: TextField(
|
||
|
decoration: InputDecoration(
|
||
|
hasFloatingPlaceholder: true,
|
||
|
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(
|
||
|
appBar: AppBar(
|
||
|
title: Text('Barcode Scanner Example'),
|
||
|
actions: <Widget>[
|
||
|
IconButton(
|
||
|
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;
|
||
|
});
|
||
|
}
|
||
|
}
|
||
|
}
|