【Flutter】QRコードの生成方法と読み取りについて

こんにちは、株式会社Pentagonでアプリ開発をしている山田です。
https://pentagon.tokyo

今回は、Flutterを使ってQRコードを生成する方法、そしてQRコードを読み取る方法を解説します。

【こんな人に読んで欲しい】

  • URLやシェアしたいデータのQRコードを生成したい方
  • FlutterでQRコードの読み取り方を知りたい人

【この記事を読むメリット】
FlutterでQRコードを作るための一連の流れを理解できます

【結論】
FlutterでQR関係を実装するのは、ライブラリを使えば容易です。

「Flutterを使ってQRコードって作れるの?」と疑問に思ってる方は、ぜひ読んでみてください。

目次

今回作成するサンプル画像

今回は次のような画像のアプリを作成します。


作成したサンプルアプリの全体のコード

以下が今回作成したサンプルアプリの全体のコードです。
Main.dart

import 'package:flutter/material.dart';
import 'package:note_sample_pj/scanner.dart';
import 'package:qr_flutter/qr_flutter.dart';

void main() {
 runApp(MyApp());
}

class MyApp extends StatelessWidget {
 @override
 Widget build(BuildContext context) {
   return MaterialApp(
     title: 'Flutter デモ',
     theme: ThemeData(
       primarySwatch: Colors.blue,
     ),
     home: MyHomePage(title: 'Flutterデモ'),
   );
 }
}

class MyHomePage extends StatefulWidget {
 MyHomePage({required this.title});

 final String title;

 @override
 _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text(widget.title),
     ),
     body: Column(
       children: [
         qrCode(),
         Center(
           child: IconButton(
               icon: Icon(Icons.camera),
               onPressed: () {
                 Navigator.push(
                   context,
                   MaterialPageRoute(builder: (context) => Scanner()),
                 );
               }),
         ),
       ],
     ),
   );
 }

 Widget qrCode() {
   return Center(
     child: QrImage(
       data: 'https://pentagon.tokyo/',
       size: 200,
     ),
   );
 }
}

Scanner.dart

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:url_launcher/url_launcher.dart';

class Scanner extends StatefulWidget {
 @override
 _ScannerState createState() => _ScannerState();
 }

class _ScannerState extends State<Scanner> {
 final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
 late QRViewController controller;

 @override
 Widget build(BuildContext context) {
   return Scaffold(
     appBar: AppBar(
       title: Text("Scanner"),
     ),
     body: Stack(
       children: [
         Column(
           children: <Widget>[
             Expanded(
               flex: 5,
               child: Stack(
                 children: [
                   QRView(
                     key: qrKey,
                     onQRViewCreated: _onQRViewCreated,
                   ),
                   Center(
                     child: Container(
                       width: 300,
                       height: 300,
                       decoration: BoxDecoration(
                         border: Border.all(
                           color: Colors.red,
                           width: 4,
                         ),
                         borderRadius: BorderRadius.circular(12),
                       ),
                     ),
                   )
                 ],
               ),
             ),
             Expanded(
               flex: 1,
               child: Center(
                 child: Text('Scan a code'),
               ),
             )
           ],
         ),
       ],
     ),
   );
 }

 void _onQRViewCreated(QRViewController controller) {
   this.controller = controller;
   controller.scannedDataStream.listen((scanData) async {
     controller.pauseCamera();
     if (await canLaunch(scanData.code)) {
       await launch(scanData.code);
       controller.resumeCamera();
     } else {
       showDialog(
         context: context,
         builder: (BuildContext context) {
           return AlertDialog(
             title: Text('Could not find viable url'),
             content: SingleChildScrollView(
               child: ListBody(
                 children: <Widget>[
                   Text('Barcode Type: ${describeEnum(scanData.format)}'),
                   Text('Data: ${scanData.code}'),
                 ],
               ),
             ),
             actions: <Widget>[
               TextButton(
                 child: Text('Ok'),
                 onPressed: () {
                   Navigator.of(context).pop();
                 },
               ),
             ],
           );
         },
       ).then((value) => controller.resumeCamera());
     }
   });
 }
}

QRコードの作り方の解説

今回は、QRコードの生成と、QRカメラ機能の追加を実施しています。

必要なパッケージ

QRコード生成に必要なパッケージは次の通りです。
・qr_flutter
https://pub.dev/packages/qr_flutter

次に今回QRカメラの追加をする際に、必要なパッケージを用意します。
・qr_code_scanner
https://pub.dev/packages/qr_code_scanner

最後にQRカメラから読み取ったURLを表示させるためのパッケージが必要になります。
・url_launcher
https://pub.dev/packages/url_launcher

以上が今回のアプリで必要なパッケージです。

QRコード生成の解説

QRを生成している箇所は以下のコードになります。

  Widget qrCode() {
   return Center(
     child: QrImage(
       data: 'https://pentagon.tokyo/',
       size: 200,
     ),
   );
 }

ここではシンプルな構成とし、dataにはQRコードを読み取った際に得られるデータ、sizeにはQRコードの大きさを指定します。

QRコード読み取りカメラの解説

ここではscanner.dartがQR読み取り用カメラの役割を果たしています。

void _onQRViewCreated(QRViewController controller) {
 this.controller = controller;
 controller.scannedDataStream.listen((scanData) async {
   controller.pauseCamera();
   if (await canLaunch(scanData.code)) {
     await launch(scanData.code);
     controller.resumeCamera();
   } else {
     showDialog(
       context: context,
       builder: (BuildContext context) {
         return AlertDialog(
           title: Text('Could not find viable url'),
           content: SingleChildScrollView(
             child: ListBody(
               children: [
                 Text('Barcode Type: ${describeEnum(scanData.format)}'),
                 Text('Data: ${scanData.code}'),
               ],
             ),
           ),
           actions: [
             TextButton(
               child: Text('Ok'),
               onPressed: () {
                 Navigator.of(context).pop();
               },
             ),
           ],
         );
       },
     ).then((value) => controller.resumeCamera());
   }
 });
}

QRViewController を使い、

 controller.scannedDataStream.listen((scanData) async {
   controller.pauseCamera();
   if (await canLaunch(scanData.code)) {
     await launch(scanData.code);
     controller.resumeCamera();
     }

ここで、QRカメラの軌道を実施しています。
If文で括っている理由は、データが受け取れなかった際、ダイアログでそのテキストを出せるようにするためです

まとめ

今回の記事はいかがだったでしょうか?
「QRコードの生成方法や、QRカメラの実装の仕方は、意外と難しくない」と感じたかもしれません。
この記事を参考に、Flutterを利用してQR関係の機能を実装してみてください。

採用情報はこちら
目次