Flutter二维码生成与扫描插件qris的使用
Flutter二维码生成与扫描插件qris的使用
qris
是一个用于解析QR Indonesian Standard (QRIS) 代码的Flutter插件。它能够将读取到的QRIS码分解成有用的信息,如商户名称、交易金额等。
功能
- 解析QRIS码为各种有用信息,包括QRIS类型、商户名称、交易金额和各类商户信息。
使用示例
从字符串解析QRIS数据
假设你已经通过某种QR阅读工具获取了一个QRIS码,并将其存储在变量 qrisData
中:
final qris = QRIS(qrisData);
debugPrint(qris.merchantName); // 输出: Baznas
qris.merchants.forEach((merchant) {
debugPrint("${merchant.globallyUniqueIdentifier} | ${merchant.merchantCriteria.toString()}");
});
// 输出: ID.CO.SHOPEE.WWW | QRISMerchantCriteria.large
debugPrint(qris.pointOfInitiation?.toString());
// 输出: QRISInitiationPoint.staticCode
从图片文件或相册中读取QRIS数据
推荐使用 barcode_finder
插件来实现从图片文件或相册中读取QRIS数据。以下是一个修改后的示例(该示例使用了 file_picker
来选择文件,你可以替换为 image_picker
):
import 'package:barcode_finder/barcode_finder.dart' as bf;
import 'package:image_picker/image_picker.dart';
Future<QRIS?> scanFile() async {
final pickedFile = await FilePicker.platform.pickFiles();
if (pickedFile != null) {
final filePath = pickedFile.files.single.path;
if (filePath != null) {
final scannedData = await bf.BarcodeFinder.scanFile(
path: filePath,
formats: [bf.BarcodeFormat.QR_CODE],
);
if (scannedData != null) {
return QRIS(scannedData);
}
}
}
return null;
}
完整示例Demo
以下是一个完整的Flutter应用程序示例,展示了如何使用 qris
插件进行二维码的扫描和解析:
// ignore_for_file: avoid_print, use_key_in_widget_constructors
import 'package:barcode_finder/barcode_finder.dart' as bf;
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:mobile_scanner/mobile_scanner.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:qris/qris.dart';
void main() {
runApp(const QRISDemoApp());
}
class QRISDemoApp extends StatelessWidget {
const QRISDemoApp();
@override
Widget build(BuildContext context) {
const defaultBorder = OutlineInputBorder();
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
elevatedButtonTheme: const ElevatedButtonThemeData(
style: ButtonStyle(
iconColor: MaterialStatePropertyAll(Colors.white),
),
),
inputDecorationTheme: const InputDecorationTheme(
border: defaultBorder,
focusedBorder: defaultBorder,
enabledBorder: defaultBorder,
errorBorder: defaultBorder,
focusedErrorBorder: defaultBorder,
isDense: true,
contentPadding: EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
),
floatingActionButtonTheme: const FloatingActionButtonThemeData(
foregroundColor: Colors.white,
),
listTileTheme: ListTileThemeData(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.0),
side: const BorderSide(color: Colors.black12),
),
),
),
home: const QRISDemoPage(),
);
}
}
class QRISDemoPage extends StatefulWidget {
const QRISDemoPage();
@override
State<QRISDemoPage> createState() => _QRISDemoPageState();
}
class _QRISDemoPageState extends State<QRISDemoPage> {
QRIS? _qris;
late final resultController = TextEditingController();
@override
void dispose() {
resultController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('QRIS Scanner Demo')),
body: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
children: [
TextField(
decoration: InputDecoration(
labelText: 'Reading Result (Raw)',
suffixIcon: IconButton(
icon: const Icon(Icons.copy),
onPressed: () {
final result = resultController.text.trim();
if (result.isEmpty) return;
Clipboard.setData(ClipboardData(text: result));
},
),
),
controller: resultController,
readOnly: true,
maxLines: 5,
),
const SizedBox(height: 24.0),
Expanded(
child: Builder(
builder: (_) {
final qris = _qris;
if (qris == null) {
return const Center(
child: Text(
'See scan results here',
textAlign: TextAlign.center,
),
);
}
final map = qris.toEncodable().entries;
return ListView.separated(
separatorBuilder: (_, __) => const SizedBox(height: 12.0),
itemCount: map.length,
itemBuilder: (_, idx) {
final entry = map.elementAt(idx);
final value = '${entry.value}';
return ListTile(
leading: Text(
'[${entry.key}]',
style: const TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
),
),
title: Text(value),
trailing: IconButton(
onPressed: () {
if (value.isEmpty) return;
Clipboard.setData(ClipboardData(text: value));
},
icon: const Icon(Icons.copy),
),
);
},
);
},
),
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Permission.camera.request().then((permission) {
if (!permission.isGranted) {
if (permission.isPermanentlyDenied) openAppSettings();
return;
}
Navigator.of(context).push(
MaterialPageRoute(builder: (_) => const QRISScannerPage()),
).then((result) {
if (result is QRIS) {
resultController.text = result.toString();
setState(() {
_qris = result;
});
}
});
});
},
child: const Icon(Icons.qr_code_2),
),
);
}
}
class QRISScannerPage extends StatefulWidget {
const QRISScannerPage();
@override
State<QRISScannerPage> createState() => _QRISScannerPageState();
}
class _QRISScannerPageState extends State<QRISScannerPage> with WidgetsBindingObserver {
late final MobileScannerController controller = MobileScannerController(
formats: [BarcodeFormat.qrCode],
);
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
controller.start();
break;
case AppLifecycleState.inactive:
controller.stop();
break;
case AppLifecycleState.paused:
controller.stop();
break;
case AppLifecycleState.detached:
break;
}
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
void onDetect(BarcodeCapture barcodes) {
for (var barcode in barcodes.barcodes) {
final rawValue = barcode.rawValue;
if (rawValue != null) {
try {
final qris = QRIS(rawValue);
Navigator.of(context).pop(qris);
break;
} catch (_) {
print(_);
}
}
}
}
void toggleFlash() {
if (controller.hasTorch) {
controller.toggleTorch();
}
}
Future<void> readFromImage() async {
final storagePermission = await Permission.storage.request();
if (!storagePermission.isGranted) {
if (storagePermission.isPermanentlyDenied) openAppSettings();
return;
}
final xFile = await ImagePicker().pickImage(source: ImageSource.gallery);
final filePath = xFile?.path;
if (filePath != null) {
final data = await bf.BarcodeFinder.scanFile(
path: filePath,
formats: [bf.BarcodeFormat.QR_CODE],
);
if (data != null) {
Navigator.of(context).pop(QRIS(data));
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('QR Scanner')),
body: Stack(
children: [
Center(child: MobileScanner(controller: controller, onDetect: onDetect)),
Padding(
padding: const EdgeInsets.only(bottom: 64.0),
child: Align(
alignment: Alignment.bottomCenter,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ValueListenableBuilder(
valueListenable: controller.torchState,
builder: (context, state, _) {
late final Widget icon;
switch (state) {
case TorchState.off:
icon = const Icon(Icons.flash_on);
break;
case TorchState.on:
icon = const Icon(Icons.flash_off);
break;
}
return ElevatedButton(onPressed: toggleFlash, child: icon);
},
),
ElevatedButton(onPressed: readFromImage, child: const Icon(Icons.image)),
],
),
),
),
],
),
);
}
}
以上代码提供了一个完整的Flutter应用示例,展示了如何使用 qris
插件进行二维码的扫描和解析。你可以根据需要进一步修改和完善这个示例。
更多关于Flutter二维码生成与扫描插件qris的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter二维码生成与扫描插件qris的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter项目中使用qr_code_scanner
和qr_flutter
插件来生成与扫描二维码的示例代码。需要注意的是,尽管qr_code_scanner
和qr_flutter
是两个流行的插件,但直接名为qris
的插件可能并不明确指向某个具体的二维码处理库。因此,我将基于这两个广泛使用的插件来演示。
1. 添加依赖
首先,在你的pubspec.yaml
文件中添加以下依赖:
dependencies:
flutter:
sdk: flutter
qr_code_scanner: ^3.0.1 # 请检查最新版本
qr_flutter: ^4.0.0 # 请检查最新版本
然后运行flutter pub get
来安装这些依赖。
2. 生成二维码
使用qr_flutter
插件生成二维码:
import 'package:flutter/material.dart';
import 'package:qr_flutter/qr_flutter.dart';
class QRCodeGenerator extends StatelessWidget {
final String qrCodeData;
QRCodeGenerator({required this.qrCodeData});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('二维码生成'),
),
body: Center(
child: QrImage(
data: qrCodeData,
size: 200,
),
),
);
}
}
你可以在你的应用中导航到这个页面并传递你想要编码的数据。
3. 扫描二维码
使用qr_code_scanner
插件扫描二维码:
首先,在你的AndroidManifest.xml
中添加相机权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus" />
然后,在你的ios/Runner/Info.plist
中添加相机使用描述:
<key>NSCameraUsageDescription</key>
<string>需要访问相机来扫描二维码</string>
接下来,创建一个扫描页面:
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
class QRCodeScannerPage extends StatefulWidget {
@override
_QRCodeScannerPageState createState() => _QRCodeScannerPageState();
}
class _QRCodeScannerPageState extends State<QRCodeScannerPage> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
QRViewController? controller;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('二维码扫描'),
),
body: Column(
children: <Widget>[
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
Expanded(
flex: 1,
child: FittedBox(
child: ControllerWidget(),
),
),
],
),
);
}
void _onQRViewCreated(QRViewController qrViewController) {
this.controller = qrViewController;
this.controller!.scannedDataStream.listen((scanData) {
setState(() {
print('二维码数据: ${scanData}');
// 在这里处理扫描到的数据
});
});
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
}
class ControllerWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () async {
final BarcodeScannerResult? result = await BarcodeScanner.scan();
if (result != null) {
print('扫描结果: ${result.rawContent}');
}
},
child: Text('使用系统相机扫描'),
),
],
);
}
}
请注意,BarcodeScanner.scan()
方法是一个平台通道调用,它可能会打开设备的原生相机应用进行扫描,而不是使用qr_code_scanner
插件的自定义相机视图。根据你的需求选择使用哪种方式。
4. 导航页面
最后,在你的主应用或任何需要的地方添加导航逻辑:
import 'package:flutter/material.dart';
import 'qr_code_generator.dart';
import 'qr_code_scanner_page.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('二维码示例'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QRCodeGenerator(qrCodeData: "https://www.example.com")),
);
},
child: Text('生成二维码'),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QRCodeScannerPage()),
);
},
child: Text('扫描二维码'),
),
],
),
),
),
);
}
}
以上代码展示了如何在Flutter应用中集成二维码生成与扫描功能。请根据你的实际需求调整代码。