flutter扫描二维码或者条形码
扫码功能
1、mobile_scanner,该插件同时支持二维码和条形码,但是使用捆绑版本会使Android打包变大 3-10M,非捆版版本会增加 600kb左右,具体可前往官网查看。
- 引入必要的包
- 通过 onScanCompleted 回调函数把扫描结果传给上级页面
import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:wallpaper/components/scan_code_animation%20.dart';
class ScanCode extends StatefulWidget {
final void Function(String result) onScanCompleted;
const ScanCode({super.key, required this.onScanCompleted});
@override
State<ScanCode> createState() => _ScanCode();
}
class _ScanCode extends State<ScanCode> {
Barcode? _barcode;
final MobileScannerController controller = MobileScannerController();
void _handleBarcode(BarcodeCapture barcodes) async {
if (mounted) {
final barcode = barcodes.barcodes.firstOrNull;
if (barcode != null) {
// 更新状态
setState(() {
_barcode = barcode;
});
// 调用回调函数
widget.onScanCompleted(barcode.displayValue ?? '');
// 停止扫描并返回
await controller.stop();
// ignore: use_build_context_synchronously
Navigator.pop(context);
}
}
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('扫描二维码或者条形码')),
backgroundColor: Colors.black,
body: Stack(
children: [
MobileScanner(
controller: controller,
onDetect: _handleBarcode,
),
// 条形码扫描动画
QrCodeScanAnimation(),
],
),
);
}
}
- 具体使用
- 在父页面,点击扫描按钮后跳转扫描页面,扫描成功后返回数据和销毁扫描页
InkWell(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ScanCode(onScanCompleted: (value) {
print(value);
})));
},
child: Icon(
Icons.qr_code_scanner,
color: Theme.of(context).colorScheme.onSurface,
size: 28,
),
)
到这里,简单的扫码功能就实现了,能够直接扫描二维码和条形码,具体支持哪些格式可自行查看官网。
通过DeepSeek添加扫码动画
- 基础扫码功能,界面啥的没有,非常简陋,稍微添加一个扫码动画
- 需求直接抛给 deepseek ,让deepseek帮我们写
- deepseek 代码如下:
import 'package:flutter/material.dart';
class QrCodeScanAnimation extends StatefulWidget {
const QrCodeScanAnimation({super.key});
@override
// ignore: library_private_types_in_public_api
_QrCodeScanAnimation createState() => _QrCodeScanAnimation();
}
class _QrCodeScanAnimation extends State<QrCodeScanAnimation>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: const Duration(seconds: 2),
vsync: this,
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: CustomPaint(
painter: ScannerPainter(_controller),
size: Size(250, 250),
),
);
}
}
class ScannerPainter extends CustomPainter {
final Animation<double> animation;
ScannerPainter(this.animation) : super(repaint: animation);
@override
void paint(Canvas canvas, Size size) {
final width = size.width;
final height = size.height;
final paintColor = Colors.blue;
final borderPaint = Paint()
..color = paintColor
..style = PaintingStyle.stroke
..strokeWidth = 3;
// 绘制四角边框
final cornerLength = 25.0;
// 左上角
canvas.drawLine(Offset.zero, Offset(cornerLength, 0), borderPaint);
canvas.drawLine(Offset.zero, Offset(0, cornerLength), borderPaint);
// 右上角
canvas.drawLine(
Offset(width, 0), Offset(width - cornerLength, 0), borderPaint);
canvas.drawLine(Offset(width, 0), Offset(width, cornerLength), borderPaint);
// 左下角
canvas.drawLine(
Offset(0, height), Offset(cornerLength, height), borderPaint);
canvas.drawLine(
Offset(0, height), Offset(0, height - cornerLength), borderPaint);
// 右下角
canvas.drawLine(Offset(width, height), Offset(width - cornerLength, height),
borderPaint);
canvas.drawLine(Offset(width, height), Offset(width, height - cornerLength),
borderPaint);
// 绘制扫描线
final linePaint = Paint()
..shader = LinearGradient(
colors: [Colors.transparent, paintColor, Colors.transparent],
stops: [0.1, 0.5, 0.9],
).createShader(Rect.fromLTWH(0, 0, width, 3))
..strokeWidth = 3;
final lineY = height * animation.value;
canvas.drawLine(
Offset(0, lineY),
Offset(width, lineY),
linePaint,
);
}
@override
bool shouldRepaint(covariant CustomPainter oldDelegate) => true;
}
- 最终效果,四个角有边框包裹,中间有一条扫描线从上到下循环执行,代码复制过来就能用,效果也不错,反正deepseek牛逼就完了。