はじめに
QRコードを読み取るアプリを作る機会があったので、ライブラリを探っていたら qr_code_scanner
っていう良さげなものがあったので、使わせていただきました。
exampleが StatefulWidget
で書かれていたのですが、riverpod
を使っていたので書き換えたバージョンを紹介します。
カメラ権限周りの記述については割愛しています。
環境
% fvm flutter --version
Flutter 3.3.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision d9111f6402 (9 weeks ago) • 2022-10-19 12:27:13 -0700
Engine • revision 3ad69d7be3
Tools • Dart 2.18.2 • DevTools 2.15.0
ソース
dart@pubspec.yaml
environment:
sdk: '>=2.18.2 <3.0.0'
dependencies:
flutter:
sdk: flutter
flutter_localizations:
sdk: flutter
flutter_riverpod: ^2.0.2
qr_code_scanner: ^1.0.1
dart@qr_code_reader_page.dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
final qrCodeProvider =
StateNotifierProvider.autoDispose<QRCodeNotifier, Barcode>((ref) {
final notifier = QRCodeNotifier();
ref.onDispose(() => notifier.controller?.dispose());
return notifier;
});
class QRCodeNotifier extends StateNotifier<Barcode> {
QRViewController? controller;
QRCodeNotifier() : super(Barcode(null, BarcodeFormat.unknown, null));
void onQRViewCreated(QRViewController controller) {
this.controller = controller;
this.controller!.scannedDataStream.listen((scanData) {
state = scanData;
});
}
}
class QRCodeReaderPage extends ConsumerWidget {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
QRCodeReaderPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final notifier = ref.watch(qrCodeProvider.notifier);
final state = ref.watch(qrCodeProvider);
final double scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
return Scaffold(
body: Column(
children: [
Expanded(
flex: 4,
child: QRView(
key: qrKey,
onQRViewCreated: notifier.onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.red,
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
onPermissionSet: (ctrl, p) =>
_onPermissionSet(context, ctrl, p),
)),
Expanded(
flex: 1,
child: FittedBox(
fit: BoxFit.contain,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
if (state.format != BarcodeFormat.unknown)
Text(
'Barcode Type: ${describeEnum(state.format)} Data: ${state.code}')
else
const Text('Scan a code'),
],
),
))
],
),
);
}
void _onPermissionSet(BuildContext context, QRViewController ctrl, bool p) {
debugPrint('${DateTime.now().toIso8601String()}_onPermissionSet $p');
if (!p) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('no Permission')),
);
}
}
}
最近主流?になりつつある riverpod
ですが、私のように書き方に苦労している人がいると思ったので紹介してみました。
必要最低限のコードですが、何かの役に立てば幸いです。