Flutter二维码扫描插件barcode_scan2的使用
Flutter二维码扫描插件barcode_scan2的使用
插件概述
barcode_scan2
是一个用于扫描2D条形码和QR码的Flutter插件。它提供了对iOS和Android平台的支持,并且在原barcode_scan
插件停止维护后,作为其替代品重生,支持空安全(null safety)。以下是该插件的一些特性:
- ✅ 扫描2D条形码
- ✅ 扫描QR码
- ✅ 控制扫描时的闪光灯
- ✅ 权限处理
开始使用
Android配置
-
添加相机权限:在
AndroidManifest.xml
中添加相机权限。<uses-permission android:name="android.permission.CAMERA" />
-
添加Kotlin支持:确保项目支持Kotlin。可以参考Kotlin官方文档进行设置。
-
修改build.gradle文件:
- 项目级
build.gradle
:buildscript { ext.kotlin_version = '1.3.61' dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
- 应用级
build.gradle
:apply plugin: 'kotlin-android' dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" }
- 项目级
-
依赖插件:在
pubspec.yaml
中添加barcode_scan2
依赖。dependencies: barcode_scan2: any
-
获取包:点击Android Studio中的"Packages get"或运行
flutter packages get
。
iOS配置
- 添加相机使用描述:在
Info.plist
中添加相机使用描述。<dict> <key>NSCameraUsageDescription</key> <string>Camera permission is required for barcode scanning.</string> </dict>
使用示例
以下是一个完整的示例代码,展示了如何使用barcode_scan2
插件进行二维码扫描,并显示扫描结果。
import 'dart:async';
import 'dart:io' show Platform;
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() => runApp(const App());
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
@override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
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
void initState() {
super.initState();
Future.delayed(Duration.zero, () async {
_numberOfCameras = await BarcodeScanner.numberOfCameras;
setState(() {});
});
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Barcode Scanner Example'),
actions: [
IconButton(
icon: const Icon(Icons.camera),
tooltip: 'Scan',
onPressed: _scan,
),
],
),
body: ListView(
shrinkWrap: true,
children: <Widget>[
if (scanResult != null)
Card(
child: Column(
children: <Widget>[
ListTile(
title: const Text('Result Type'),
subtitle: Text(scanResult!.type.toString()),
),
ListTile(
title: const Text('Raw Content'),
subtitle: Text(scanResult!.rawContent),
),
ListTile(
title: const Text('Format'),
subtitle: Text(scanResult!.format.toString()),
),
ListTile(
title: const Text('Format note'),
subtitle: Text(scanResult!.formatNote),
),
],
),
),
const ListTile(
title: Text('Camera selection'),
dense: true,
enabled: false,
),
RadioListTile(
onChanged: (v) => setState(() => _selectedCamera = -1),
value: -1,
title: const Text('Default camera'),
groupValue: _selectedCamera,
),
...List.generate(
_numberOfCameras,
(i) => RadioListTile(
onChanged: (v) => setState(() => _selectedCamera = i),
value: i,
title: Text('Camera ${i + 1}'),
groupValue: _selectedCamera,
),
),
const ListTile(
title: Text('Button Texts'),
dense: true,
enabled: false,
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Flash On',
),
controller: _flashOnController,
),
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Flash Off',
),
controller: _flashOffController,
),
),
ListTile(
title: TextField(
decoration: const InputDecoration(
floatingLabelBehavior: FloatingLabelBehavior.always,
labelText: 'Cancel',
),
controller: _cancelController,
),
),
if (Platform.isAndroid) ...[
const ListTile(
title: Text('Android specific options'),
dense: true,
enabled: false,
),
ListTile(
title: Text(
'Aspect tolerance (${_aspectTolerance.toStringAsFixed(2)})',
),
subtitle: Slider(
min: -1,
value: _aspectTolerance,
onChanged: (value) {
setState(() {
_aspectTolerance = value;
});
},
),
),
CheckboxListTile(
title: const Text('Use autofocus'),
value: _useAutoFocus,
onChanged: (checked) {
setState(() {
_useAutoFocus = checked!;
});
},
),
],
const ListTile(
title: Text('Other options'),
dense: true,
enabled: false,
),
CheckboxListTile(
title: const Text('Start with flash'),
value: _autoEnableFlash,
onChanged: (checked) {
setState(() {
_autoEnableFlash = checked!;
});
},
),
const ListTile(
title: Text('Barcode formats'),
dense: true,
enabled: false,
),
ListTile(
trailing: Checkbox(
tristate: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
value: selectedFormats.length == _possibleFormats.length
? true
: selectedFormats.isEmpty
? false
: null,
onChanged: (checked) {
setState(() {
selectedFormats = [
if (checked ?? false) ..._possibleFormats,
];
});
},
),
dense: true,
enabled: false,
title: const Text('Detect barcode formats'),
subtitle: const Text(
'If all are unselected, all possible '
'platform formats will be used',
),
),
..._possibleFormats.map(
(format) => CheckboxListTile(
value: selectedFormats.contains(format),
onChanged: (i) {
setState(
() => selectedFormats.contains(format)
? selectedFormats.remove(format)
: selectedFormats.add(format),
);
},
title: Text(format.toString()),
),
),
],
),
),
);
}
Future<void> _scan() async {
try {
final result = await BarcodeScanner.scan(
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,
),
),
);
setState(() => scanResult = result);
} on PlatformException catch (e) {
setState(() {
scanResult = ScanResult(
rawContent: e.code == BarcodeScanner.cameraAccessDenied
? 'The user did not grant the camera permission!'
: 'Unknown error: $e',
);
});
}
}
}
高级用法
你可以通过传递选项来定制扫描行为。以下是支持的选项及其说明:
选项 | 类型 | 描述 | 支持平台 |
---|---|---|---|
strings.cancel |
String |
iOS上的取消按钮文本 | iOS only |
strings.flash_on |
String |
闪光灯开启按钮文本 | iOS + Android |
strings.flash_off |
String |
闪光灯关闭按钮文本 | iOS + Android |
restrictFormat |
BarcodeFormat[] |
限制识别的格式 | iOS + Android |
useCamera |
int |
使用的摄像头索引(见BarcodeScanner.numberOfCameras ) |
iOS + Android |
autoEnableFlash |
bool |
开始扫描时自动启用闪光灯 | iOS + Android |
android.aspectTolerance |
double |
Android上启用自动对焦 | Android only |
android.useAutoFocus |
bool |
设置Android上使用的自动对焦选项 | Android only |
常见问题
Android “Could not find org.jetbrains.kotlin:kotlin-stdlib-jre…”
解决方案是将org.jetbrains.kotlin:kotlin-stdlib-jre
改为org.jetbrains.kotlin:kotlin-stdlib-jdk
。详情请参阅StackOverflow。
通过以上步骤和示例代码,你应该能够顺利地在Flutter项目中集成并使用barcode_scan2
插件进行二维码扫描。如果有任何问题或需要进一步的帮助,请随时提问!
更多关于Flutter二维码扫描插件barcode_scan2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter二维码扫描插件barcode_scan2的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是如何在Flutter项目中使用barcode_scan2
插件来实现二维码扫描功能的代码示例。
1. 添加依赖
首先,你需要在pubspec.yaml
文件中添加barcode_scan2
依赖:
dependencies:
flutter:
sdk: flutter
barcode_scan2: ^2.0.0 # 确保使用最新版本,版本号可能会更新
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中(例如main.dart
),导入barcode_scan2
插件:
import 'package:barcode_scan2/barcode_scan2.dart';
import 'package:flutter/material.dart';
3. 创建扫描页面
接下来,创建一个按钮来触发二维码扫描,并处理扫描结果。以下是一个简单的示例:
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: ScanPage(),
);
}
}
class ScanPage extends StatefulWidget {
@override
_ScanPageState createState() => _ScanPageState();
}
class _ScanPageState extends State<ScanPage> {
String _result = "";
Future<void> _scanQR() async {
try {
String result = await BarcodeScanner.scan();
setState(() {
_result = result;
});
} on PlatformException catch (e) {
if (e.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
_result = "相机权限被拒绝,请检查应用权限设置。";
});
} else {
setState(() {
_result = "扫描失败: ${e.message}";
});
}
} catch (e) {
setState(() {
_result = "扫描失败: $e";
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('二维码扫描示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
_result,
style: TextStyle(fontSize: 24),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _scanQR,
child: Text('扫描二维码'),
),
],
),
),
);
}
}
4. 请求权限(可选)
在某些平台上(特别是Android),你可能需要在运行时请求相机权限。你可以在AndroidManifest.xml
中声明权限,并使用permission_handler
插件来请求权限(如果需要)。
在AndroidManifest.xml
中声明权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
使用permission_handler
插件请求权限(如果你选择这样做):
首先,在pubspec.yaml
中添加permission_handler
依赖:
dependencies:
permission_handler: ^8.0.0 # 确保使用最新版本,版本号可能会更新
然后在你的代码中请求权限:
import 'package:permission_handler/permission_handler.dart';
Future<void> _requestCameraPermission() async {
var status = await Permission.camera.status;
if (!status.isGranted) {
var result = await Permission.camera.request();
if (!result.isGranted) {
_result = "相机权限被拒绝,请检查应用权限设置。";
setState(() {});
}
}
}
// 在_scanQR方法之前调用_requestCameraPermission
Future<void> _scanQR() async {
await _requestCameraPermission();
// 接下来的代码与之前相同...
}
总结
以上代码展示了如何在Flutter项目中使用barcode_scan2
插件来实现二维码扫描功能。包括添加依赖、导入插件、创建扫描页面以及请求相机权限(可选)。希望这能帮助你快速上手二维码扫描功能。