1.添加依赖
1.1 package依赖
在android项目目录下的pubspec.yaml文件中添加如下代码:
# 二维码扫描
qr_code_scanner: ^0.5.2
1.2 资源依赖
需要一些图片美化项目,因此:
-
在android项目目录下的assets/images/qrcode中添加需要的图片
-
在pubspec.yaml文件中加入图片路径(flutter需要在该文件中配置路径才能找到图片资源)
2.具体步骤
2.1 创建文件
在android项目中的pages目录下新建目录qrcode和文件qrcode_index.dart
2.2 实现步骤
flutter将代码分为界面层和逻辑层,界面层负责布局、优化显示,逻辑层负责实现功能。
2.2.1 界面实现
界面整体布局如下图所示
- 整体分为两层,第一层为扫描层,用于扫描二维码
- 第二层为装饰层,包括上方的返回按钮、下方文字和手电筒
2.2.2 逻辑实现
-
扫描区域实现
/// 通过QRView创建扫描区域 QRView({ required Key key, /// key值 required this.onQRViewCreated, /// 创建扫描区域功能,在该方法中实现对扫描到的数据的监听 this.overlay, /// 悬浮功能,如图中所示的四部分绿色弧形 this.onPermissionSet /// 相机权限请求 })
-
手电筒功能实现
qrcontroller.toggleFlash()
3.核心代码
3.1 界面代码
/// 界面层
class QRCodePage extends StatelessWidget {
QRCodePage({Key? key}) : super(key: key);
/// 界面层和逻辑层通过vm实现数据的传递
final QRCodePageController vm = Get.put(QRCodePageController());
@override
Widget build(BuildContext context) {
return SafeArea(
// top: false,
child: BaseScaffold(
body: Stack(
children: [
/// 此处为二维码扫描区域的实现部分
vm._buildQrView(context),
Column(
children: [
Expanded(
child: Column(
children: [
Row(
children: [
/// 第二层中返回值按钮
const BackButton(
color: Colors.white,
)
],
)
],
)),
Container(
child: SizedBox(
width: 600.w,
height: 600.w,
)),
/// 第二层中显示文字
Expanded(
child: Container(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
"扫二维码",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w200,
fontSize: 30.sp),
),
],
),
SizedBox(
height: 100.w,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
/// 第二层中手电筒功能实现,实现点击切换图标并刷新当前区域的功能
Obx(() {
return GestureDetector(
onTap: () {
// 手电筒功能
vm.qrcontroller.toggleFlash();
vm.switchLight.toggle();
},
child: vm.switchLight.value
? Image.asset(
'assets/images/qrcode/手电筒-开.png',
width: 100.w,
height: 100.w,
fit: BoxFit.cover,
)
: Image.asset(
'assets/images/qrcode/手电筒-关.png',
width: 100.w,
height: 100.w,
fit: BoxFit.cover));
})
],
)
],
),
)),
],
)
],
),
),
);
}
}
3.2 逻辑代码
/// 逻辑层
class QRCodePageController extends GetxController {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
final Rx<Barcode> result = Barcode('', BarcodeFormat.unknown, null).obs;
late final QRViewController qrcontroller;
///手电筒开关
final RxBool switchLight = false.obs;
///创建二维码视窗
void _onQRViewCreated(QRViewController ctr) {
qrcontroller = ctr;
/// 验证客户端是安卓还是苹果系统
if (Platform.isAndroid) {
qrcontroller.pauseCamera();
} else if (Platform.isIOS) {
qrcontroller.resumeCamera();
}
/// 获取监听数据
qrcontroller.scannedDataStream.listen((Barcode scanData) {
// setState(() {
// result = scanData;
// });
result(scanData);
if (result.value.code != null) {
/// 显示得到的数据
BotToast.showText(text: result.value.code);
}
});
// controller.dispose();
}
Widget _buildQrView(BuildContext context) {
return QRView(
key: qrKey,
/// 创建扫描视图窗口
onQRViewCreated: _onQRViewCreated,
/// 悬浮窗设置
overlay: QrScannerOverlayShape(
borderColor: Colors.green,
borderRadius: 20.w,
borderLength: 60.w,
borderWidth: 20.w,
cutOutSize: 600.w),
onPermissionSet: (QRViewController ctrl, bool p) =>
_onPermissionSet(context, ctrl, p),
);
}
void closeQRcode() {
qrcontroller.dispose();
}
/// 请求相机权限
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')),
);
}
}
}