FlutterでＱＲコードを作ってみた

# はじめに
パッケージを使うだけで簡単に作れるQRコードリーダーです。

初投稿 and 自分用アプリでアウトプットも兼ねてるので、ツッコミ所あったら優しくお願いします。

#機能
【1】QRコードの読み取り(ギャラリー内とカメラに対応)　⇒Firebase MLkit不要
【2】QRコードの生成

# 環境
Windows10 
AndroidStudio4.1

# 参考にしたレイアウト
https://www.youtube.com/watch?v=Hq-Ciuc6k0Y
この動画のコードで、詳細は動画内で確認できるので省略します。
※英語字幕のみの動画ですが、ホットリロード多めなので内容は理解できると思います。

#必要なパッケージ
pubspec.yaml に qr_flutter を追加します。

```pubspec.yaml
dependencies:
  qr_flutter: ^3.2.0
  url_launcher: ^5.7.2
  super_qr_reader: ^2.0.2
  

```


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [Chapter1](#Chapter1)
1. [Chapter2](#Chapter2)
2. [Chapter3](#Chapter3)
3. [Chapter4](#Chapter4)
1. [参考文献](#reference)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# Chapter1 トップ画面の作成

```main.dart
import 'package:flutter/material.dart';
import 'package:tahara_qrcode_reader/HomePage.dart';


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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: MyHomePage(),
    );
  }
}

```
mainからMyHomePageを呼び出し

```HomePage.dart
import 'package:flutter/material.dart';
import 'package:tahara_qrcode_reader/QR%20Generator/QRGenerator.dart';
import 'package:tahara_qrcode_reader/ScanQR.dart';

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: Text("QRスキャン / QR作成"),
      ),
      body: Container(
        height: MediaQuery
            .of(context)
            .size
            .height,
        child: SingleChildScrollView(
          child: ConstrainedBox(
            constraints: BoxConstraints(
                minHeight: (MediaQuery
                    .of(context)
                    .size
                    .height) -
                    AppBar().preferredSize.height -
                    kToolbarHeight),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceAround,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                CircleAvatar(
                  backgroundImage: AssetImage(
                      "assets/images/aho5.jpg"
                  ),
                  foregroundColor: Colors.transparent,
                  backgroundColor: Colors.transparent,
                  radius: 150,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                  children: [
                    Hero(tag: "スキャン QR",
                      child: Container(
                        width: ((MediaQuery
                            .of(context)
                            .size
                            .width) / 2) - 45,
                        height: 50,
                        child: OutlineButton(
                          focusColor: Colors.red,
                          highlightColor: Colors.blue,
                          hoverColor: Colors.lightBlue[100],
                          borderSide: BorderSide(width: 3, color: Colors.blue),
                          shape: StadiumBorder(),
                          child: Text("QRをスキャン", style: TextStyle(fontSize: 15),
                          ),
                          onPressed: () {
                            Navigator.push(context, MaterialPageRoute(
                                builder: (context) => ScanQR()));
                          },
                        ),
                      ),
                    ),
                    SizedBox(width: 25,),
                    Container(
                      width: ((MediaQuery
                          .of(context)
                          .size
                          .width) / 2) - 45,
                      height: 50,
                      child: OutlineButton(
                        focusColor: Colors.red,
                        highlightColor: Colors.blue,
                        hoverColor: Colors.lightBlue[100],
                        borderSide: BorderSide(width: 3, color: Colors.blue),
                        shape: StadiumBorder(),
                        child: Text("QRを作成", style: TextStyle(fontSize: 17),
                        ),
                        onPressed: () {
                          Navigator.push(context, MaterialPageRoute(
                              builder: (context) => QRGenerator()));
                        },
                      ),
                    ),

                  ],
                )

              ],),

          ),
        ),
      ),
    );
  }
}
```
正直この辺は「参考にしたレイアウト」のほぼ丸コピ。
ボタン部分を「QRをスキャン」と「QRを作成」に変更
あとは CircleAvatar内に好きな画像を入れるだけ


<a id="#Chapter2"></a>
# Chapter2 QRスキャン部分
まずはコードから、そのあと解説

```ScanQR.dart
import 'package:flutter/material.dart';
import 'package:super_qr_reader/super_qr_reader.dart';
import 'package:url_launcher/url_launcher.dart';

class ScanQR extends StatefulWidget {
  ScanQR({Key key}) : super(key: key);

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

String qrData = "No data found!";
var data;
bool hasdata = false;

class _ScanQRState extends State<ScanQR> {
  @override
  Widget build(BuildContext context) {
    return Hero(
        tag: "QRをスキャン",
        child: Scaffold(
          appBar: AppBar(
            title: Text("QRスキャナー"),
          ),
          body: Container(
            width: double.infinity,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Flexible(
                      child: Text(
                        "URLにアクセス: ${(qrData)}",
                        textAlign: TextAlign.center,
                        style: TextStyle(
                          fontSize: 20,
                        ),
                      ),
                    ),
                    IconButton(
                      icon: Icon(Icons.launch_outlined),
                      onPressed: hasdata
                          ? () async {
                              if (await canLaunch(qrData)) {
                                await launch(qrData);
                              } else {
                                throw "Could not Launch";
                              }
                            }
                          : null,
                    ),
                  ],
                ),
                SizedBox(
                  height: 20,
                ),
                Container(
                  width: ((MediaQuery.of(context).size.width) / 2) - 45,
                  height: 35,
                  child: OutlineButton(
                    focusColor: Colors.red,
                    highlightColor: Colors.blue,
                    hoverColor: Colors.lightBlue[100],
                    borderSide: BorderSide(width: 3, color: Colors.blue),
                    shape: StadiumBorder(),
                    child: Text(
                      "QRコードを読み込む",
                      style: TextStyle(fontSize: 11),
                    ),
                    onPressed: () async {
                      String results = await Navigator.push(
                        context,
                        MaterialPageRoute(builder: (context) => ScanView()),
                      );
                      if (results != null) {
                        setState(() {
                          qrData = results;
                          hasdata = true;
                        });
                      }
                    },
                  ),
                )
              ],
            ),
          ),
        ));
  }
}
```
ここからは「super_qr_reader」と「url_launcher」を使用
動画内のコードを一部編集。

【1】OnPressedから「super_qr_reader」のスキャン部分の「ScanView()」だけをもってきて、
取得したQRから取得したURLを、定義しといた「qrData」に代入⇒同じく定義しといた「hasdata」を、if文内でtrueに変更
(このへんは曖昧だけど、記述しなかったらランチャーが作動しなかったので、鍵のような役割かと思います。)

【2】「qrData」にURLが代入された後、「url_launcher」で遷移可能にする。
このへんは動画のコード丸パクリですが、「pub.dev」を見る限り、同じようなコードだったので
特にイジる必要はないかと

この二つのパッケージが偉大すぎる・・。

<a id="#Chapter3"></a>
# Chapter3 トップ画面の作成

いじれる自信がなかったので丸コピ
https://github.com/vijayinyoutube/QRScanner/tree/master/lib/QR%20Generator

強いて言うなら、海外の人が作成してるので、アイコンボタンやコメント部分は日本語に変更するなど

<a id="#Chapter4"></a>
# Chapter4 補足
「super_qr_reader」も作成者が海外の人のため、コメントを変更したい場合は、「scan_view」⇒「QrcodeReaderView」の順番でF4押していけばファイルに辿りつくので、編集可能です。

「"assets/tool_img.png"」の部分がギャラリーアクセス部分で、width/heightでサイズ変更可能
※そのあたりにコメントつける方法がわからないのでわかる方教えてほしいです

以上




<a id="#reference"></a>
# 参考文献
・ https://www.youtube.com/watch?v=Hq-Ciuc6k0Y
・https://github.com/vijayinyoutube/QRScanner