QR Code Scan을 이용하기 위해
qr_code_scanner Package를 설치해야 합니다.
https://pub.dev/packages/qr_code_scanner
pubspec.yaml 에서 추가해 줍니다.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
qr_code_scanner: ^0.6.1
Android > app > build.gradle 에서 최소 minSdkVersion은 20번입니다.
AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA"/>
AndroidManifest에 카메라 권한을 설정해 줍니다.
class QrScan extends StatefulWidget {
const QrScan({Key? key}) : super(key: key);
@override
State<QrScan> createState() => _QrScanState();
}
class _QrScanState extends State<QrScan> {
final qrKey = GlobalKey(debugLabel: 'QR');
Barcode? barcode;
QRViewController? controller;
@override
void dispose() {
controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
alignment: Alignment.center,
children: [
buildQrView(context),
Positioned(bottom: 10, child: buildResult()),
Positioned(top: 30, right: 30, child: buildControlResult()),
Positioned(
top: Get.mediaQuery.padding.top + 8,
left: 10,
child: Text(
'QR Code Scan',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.cyan.withOpacity(0.7),
),
),
),
],
),
);
}
Widget buildResult() {
if (barcode != null) {
controller?.pauseCamera();
Future.microtask(() {
Navigator.push(context, MaterialPageRoute(builder: (context) =>
사용자Web(uri: barcode!.code.toString())));
controller?.resumeCamera();
});
}
return Column(
children: [
Text(
barcode != null ? 'Result : ${barcode!.code}' : 'Scan a code!',
maxLines: 3,
style: const TextStyle(color: grayColor),
),
const Text(
'Qr 코드 용지를 사각 안에 맞혀 스캔해 주세요',
style: TextStyle(color: grayColor),
),
],
);
}
Widget buildQrView(BuildContext context) => QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.cyanAccent,
borderRadius: 10,
borderLength: 20,
borderWidth: 10,
cutOutSize: MediaQuery.of(context).size.width * 0.8),
);
void onQRViewCreated(QRViewController _controller) {
controller = _controller;
controller!.scannedDataStream.listen((scanData) async {
setState(() {
barcode = scanData;
});
});
}
}
final qrKey = GlobalKey(debugLabel: 'QR');
Barcode? barcode;
QRViewController? controller;
@override
void dispose() {
controller?.dispose();
super.dispose();
}
Scanner를 실행하기 위한 기본 설정 값입니다.
controller에서 모든 작동이 이루어집니다.
카메라 플래시 설정도 controller에 들어 있으니 링크된 qr_code_scanner 페이지에서 확인해 보시기 바랍니다.
앱이 종료될 때 dispose()에서 controller를 닫아 주시면 됩니다.
Widget buildQrView(BuildContext context) => QRView(
key: qrKey,
onQRViewCreated: onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Colors.cyanAccent,
borderRadius: 10,
borderLength: 20,
borderWidth: 10,
cutOutSize: MediaQuery.of(context).size.width * 0.8),
);
void onQRViewCreated(QRViewController _controller) {
controller = _controller;
controller!.scannedDataStream.listen((scanData) async {
setState(() {
barcode = scanData;
});
});
}
QrScannerOverlayShape => 아래 실행된 모습을 보시면 화면 중앙의 사각형 스캔 영약을 설정해 줍니다.
onQRViewCreated => 화면에 QR용지를 촬영하면 barcode에 스캔된 데이터가 저장됩니다.
setState() => barcode에 값이 들어오면 buildResult 위젯에서 들어온 값을 처리하게 됩니다. (아래 코드)
Widget buildResult() {
if (barcode != null) {
controller?.pauseCamera();
Future.microtask(() {
Navigator.push(context, MaterialPageRoute(builder: (context) =>
LottoWeb(uri: barcode!.code.toString())));
controller?.resumeCamera();
});
}
return Column(
children: [
Text(
barcode != null ? 'Result : ${barcode!.code}' : 'Scan a code!',
maxLines: 3,
style: const TextStyle(color: grayColor),
),
const Text(
'Qr 코드 용지를 사각 안에 맞혀 스캔해 주세요',
style: TextStyle(color: grayColor),
),
],
);
}
controller?.pauseCamera() => barcode에 값이 들어왔다면 카메라를 잠시 멈추게 합니다. 만약 이렇게 하지 않으면 계속 같은 값이 연속으로 들어와 buildResult가 들어온 값만큼 실행되어 Navigator.push가 그 값만큼 실행됩니다.
원하지 않는 결과를 초래하게 됩니다.
Future.microtask(() {
Navigator.push(context, MaterialPageRoute(builder: (context) =>
사용자Web(uri: barcode!.code.toString())));
controller?.resumeCamera();
});
Future.microtask의 역할은 barcode.code의 값이 완벽하게 넘어올 때까지 기다렸다 안의 내용을 실행시켜 줍니다.
위 코드 없이 실행되면 Navigator가 작동은 하지만 디버그 콘솔에서 넘어갈 때 오류를 확인할 수 있습니다.
같은 조건의 대기 코드로
Future.delayed(Duration.zero, () {
// 이동
));
두 개 중 하나를 사용하시면 됩니다.
% 사용자 Web(uri: barcode!.code.toString()) => 사용자가 직접 만든 웹뷰가 있다면 barcode데이터를 넘겨 결과를 확인하는 곳입니다. %
만약 그냥 결과 값만 확인을 원하시면 Column에서 처리되니 Navigator 코드는 주석처리하시면 됩니다.
controller?. resumeCamera() => 카메라를 다시 활성화시켜 줍니다.
실행된 모습
'Flutter' 카테고리의 다른 글
플러터(Flutter) - 외부 데이터 불러올때 try / catch 오류(error) 처리 (0) | 2022.07.13 |
---|---|
플러터(Flutter) 3.0 - QR Code Scanner 검은 화면 해결(qr_code_scanner) (0) | 2022.06.21 |
플러터(Flutter) - 이미지 메뉴(Image Menu) (0) | 2022.01.17 |
플러터(Flutter) - 앱의 폰트 크기 유지 (0) | 2021.05.01 |
Flutter : 플러터 기존 프로젝트 2.0 으로 마이그레이션 하기 (0) | 2021.04.25 |