Flutter二维码扫描插件fepe_qr_code_scanner的使用
项目状态
Project in Maintenance Mode Only
由于此插件所依赖的基础框架(Android上的zxing
和iOS上的MTBBarcodeScanner
)均已停止维护,因此此插件目前仅处于维护模式。只有在修复错误和进行小范围增强时才会考虑更新。
我正在开发一个新的插件mobile_scanner,它使用了MLKit的最新版本来检测条形码和二维码。在Android上,它还使用了CameraX的最新版本,在iOS上则使用了AVFoundation以实现最佳的相机性能。
QR Code Scanner
截图
Android


iOS


扫描二维码获取结果
当二维码被识别时,识别出的文本将存储在类型为Barcode
的result
变量中,其中包含输出文本属性code
(类型为String
)和扫描码类型属性format
(类型为枚举BarcodeFormat
)。
class _QRViewExampleState extends State<QRViewExample> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
Barcode? result;
QRViewController? controller;
[@override](/user/override)
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller?.pauseCamera(); // 暂停Android摄像头
} else if (Platform.isIOS) {
controller?.resumeCamera(); // 恢复iOS摄像头
}
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(
flex: 5,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
Expanded(
flex: 1,
child: Center(
child: (result != null)
? Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
: Text('Scan a code'),
),
)
],
),
);
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
[@override](/user/override)
void dispose() {
controller?.dispose();
super.dispose();
}
}
Android集成
为了使用该插件,请更新以下Gradle配置:
-
在
android/build.gradle
中:ext.kotlin_version = '1.5.10' classpath 'com.android.tools.build:gradle:4.2.0'
-
在
android/gradle/wrapper/gradle-wrapper.properties
中:distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip
-
在
android/app/build.gradle
中:minSdkVersion 20
警告:如果您使用的是Flutter Beta或Dev通道(如1.25或1.26),可能会遇到以下错误:
java.lang.AbstractMethodError: abstract method "void io.flutter.plugin.platform.PlatformView.onFlutterViewAttached(android.view.View)"
这是一个已知的Flutter Bug,可以通过在gradle.properties
文件中添加以下内容解决:
android.enableDexingArtifactTransform=false
iOS集成
为了在iOS上使用该插件,请在Info.plist
文件中添加以下内容:
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan QR codes</string>
Web集成
在web/index.html
中添加以下脚本:
<script src="https://cdn.jsdelivr.net/npm/jsqr@1.3.1/dist/jsQR.min.js"></script>
注意:在Web端,仅支持QR码的扫描,其他条形码和二维码无法扫描。此外,Web支持仍处于早期阶段,功能如闪光灯、暂停或恢复尚未实现,且相机预览可能不完全适应周围约束。
切换前后摄像头
默认情况下,使用后置摄像头。切换到前置摄像头:
await controller.flipCamera();
开启/关闭闪光灯
默认情况下,闪光灯关闭。切换闪光灯状态:
await controller.toggleFlash();
暂停/恢复摄像头
暂停摄像头流和扫描器:
await controller.pauseCamera();
恢复摄像头流和扫描器:
await controller.resumeCamera();
示例代码
以下是完整的示例代码,展示了如何使用fepe_qr_code_scanner
插件:
import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:fepe_qr_code_scanner/qr_code_scanner.dart';
void main() => runApp(const MaterialApp(home: MyHome()));
class MyHome extends StatelessWidget {
const MyHome({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Flutter Demo Home Page')),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => const QRViewExample(),
));
},
child: const Text('qrView'),
),
),
);
}
}
class QRViewExample extends StatefulWidget {
const QRViewExample({Key? key}) : super(key: key);
[@override](/user/override)
State<StatefulWidget> createState() => _QRViewExampleState();
}
class _QRViewExampleState extends State<QRViewExample> {
Barcode? result;
QRViewController? controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
[@override](/user/override)
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller?.pauseCamera();
}
controller?.resumeCamera();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
Expanded(flex: 4, child: _buildQrView(context)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
if (result != null)
Text(
'Barcode Type: ${describeEnum(result!.format)} Data: ${result!.code}')
else
const Text('Scan a code'),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.toggleFlash();
setState(() {});
},
child: FutureBuilder(
future: controller?.getFlashStatus(),
builder: (context, snapshot) {
return Text('Flash: ${snapshot.data}');
},
)),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.flipCamera();
setState(() {});
},
child: FutureBuilder(
future: controller?.getCameraInfo(),
builder: (context, snapshot) {
if (snapshot.data != null) {
return Text(
'Camera facing ${describeEnum(snapshot.data!)}');
} else {
return const Text('loading');
}
},
)),
)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.pauseCamera();
},
child: const Text('pause', style: TextStyle(fontSize: 20)),
),
),
Container(
margin: const EdgeInsets.all(8),
child: ElevatedButton(
onPressed: () async {
await controller?.resumeCamera();
},
child: const Text('resume', style: TextStyle(fontSize: 20)),
),
)
],
),
],
),
),
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
var scanArea = (MediaQuery.of(context).size.width < 400 || MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) => _onPermissionSet(context, ctrl, p),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
log('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
[@override](/user/override)
void dispose() {
controller?.dispose();
super.dispose();
}
}
更多关于Flutter二维码扫描插件fepe_qr_code_scanner的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter二维码扫描插件fepe_qr_code_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
flutter_qr_code_scanner
是一个用于在 Flutter 应用中扫描二维码的插件。它是一个基于 mobile_scanner
的插件,提供了简单易用的 API 来扫描二维码和条形码。
安装
首先,将 flutter_qr_code_scanner
添加到你的 pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
flutter_qr_code_scanner: ^latest_version
然后运行 flutter pub get
来安装依赖。
基本用法
-
导入包
在你的 Dart 文件中导入
flutter_qr_code_scanner
:import 'package:flutter_qr_code_scanner/flutter_qr_code_scanner.dart';
-
创建 QRCodeScanner 控件
使用
QRCodeScanner
控件来显示摄像头并扫描二维码:class QRScannerScreen extends StatefulWidget { @override _QRScannerScreenState createState() => _QRScannerScreenState(); } class _QRScannerScreenState extends State<QRScannerScreen> { final GlobalKey qrKey = GlobalKey(debugLabel: 'QR'); QRViewController? controller; String? result; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('QR Code Scanner'), ), body: Column( children: <Widget>[ Expanded( flex: 5, child: QRView( key: qrKey, onQRViewCreated: _onQRViewCreated, ), ), Expanded( flex: 1, child: Center( child: Text('Scan result: ${result ?? "No data"}'), ), ), ], ), ); } void _onQRViewCreated(QRViewController controller) { this.controller = controller; controller.scannedDataStream.listen((scanData) { setState(() { result = scanData.code; }); }); } @override void dispose() { controller?.dispose(); super.dispose(); } }
-
处理扫描结果
在
_onQRViewCreated
方法中,你可以监听scannedDataStream
来获取扫描到的二维码数据。每当扫描到一个新的二维码时,scannedDataStream
会发出一个包含二维码数据的Barcode
对象。 -
权限处理
确保你的应用有摄像头的使用权限。你可以在
AndroidManifest.xml
和Info.plist
中添加相应的权限配置。Android:
<uses-permission android:name="android.permission.CAMERA" />
iOS:
<key>NSCameraUsageDescription</key> <string>We need access to your camera to scan QR codes</string>
-
运行应用
现在你可以运行你的 Flutter 应用,并使用
QRScannerScreen
来扫描二维码了。
高级用法
-
控制摄像头闪光灯
你可以通过
controller
来控制摄像头的闪光灯:controller?.toggleFlash();
-
暂停和恢复扫描
你可以通过
controller
来暂停和恢复扫描:controller?.pauseCamera(); controller?.resumeCamera();