[Day13] Flutter with GetX qr_flutter & qr_code_scanner

产生QRCode qr_flutter

Page的部分 用column分配元件位置 
中间的QrImage 外层包了一个GesutreDetector, 接收点击事件
gapless属性则是可以调整QRCode的方格之间有没有一个小的gap细线分割

class QRCodePage extends GetView<QRCodePageController> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: Text('QRCodePage')),
        body: SafeArea(
            child: SizedBox.expand(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Text('Scan QRCode', style: TextStyle(fontSize: 18)),
              Obx(
                () => GestureDetector(
                  onTap: () => controller.isGapless = !controller.isGapless,
                  child: SizedBox(
                    height: Get.width * 0.8,
                    width: Get.width * 0.8,
                    child: QrImage(
                      data: controller.qrCodeData,
                      version: QrVersions.auto,
                      size: Get.width * 0.7,
                      gapless: controller.isGapless,
                    ),
                  ),
                ),
              ),
              CupertinoButton(
                child: Text("QR code Scan"),
                color: Colors.blue,
                onPressed: () => Get.toNamed(AppRoutes.QRCodeScanPage),
              ),
            ],
          ),
        )));
  }
}

QRCodePageController的部分
qrCodeData带入QRCode被扫到後呈现的内容,
isGapless则是用GetX的Obx() 将Widget作Gap的变换

class QRCodePageController extends GetxController {
  final _qrCodeData = ''.obs;
  set qrCodeData(value) => this._qrCodeData.value = value;
  get qrCodeData => this._qrCodeData.value;

  final _isGapless = false.obs;
  set isGapless(value) => this._isGapless.value = value;
  get isGapless => this._isGapless.value;

  @override
  void onInit() {
    qrCodeData = 'https://ithelp.ithome.com.tw/2021ironman';
    super.onInit();
  }
}

https://cdn-images-1.medium.com/max/800/1*Exm-Rig99ZR_8Bf3mI7eVw.png


开启相机扫QRCode qr_code_scanner

需先设定
Android的Kotlin&gradle版本
iOS info.plist的权限设定
fjjpATJvCHbyO7ujqIqqMA

在扫描的页面 用GetX的Obx判断是否有扫描结果,
有 则显示扫描到的资讯buildScanResultView(),
没有则显示相机等待有扫描到结果buildQrView(),

class QRCodeScanPage extends GetView<QRCodeScanPageController> {
  final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Obx(() => controller.scanResult.code == ""
          ? _buildQrView(context)
          : _buildScanResultView(context)),
    );
  }
  //扫描到的结果Widget
  Widget _buildScanResultView(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Text(controller.scanResult.code),
          ),
          CupertinoButton(
            onPressed: () {
              controller.cleanScanResult();
              Get.back();
            },
            child: Text(
              "确认并返回",
              style: TextStyle(fontSize: 18),
            ),
          ),
        ],
      ),
    );
  }
  
  //开启相机扫描中的Widget
  Widget _buildQrView(BuildContext context) {
    var scanArea = Get.width;
    return Stack(
      children: [
        QRView(
          key: qrKey,
          onQRViewCreated: controller.onQRViewCreated,
          overlay: QrScannerOverlayShape(
              borderColor: Colors.red,
              borderRadius: 10,
              borderLength: 30,
              borderWidth: 10,
              cutOutSize: scanArea),
        ),
        Positioned.fill(
          child: Align(
            alignment: Alignment.bottomCenter,
            child: CupertinoButton(
                color: Colors.blue,
                onPressed: () => Get.back(),
                child: Text('返回')),
          ),
        ),
      ],
    );
  }
}

https://cdn-images-1.medium.com/max/800/1*MUo9LMfUI_oi9YuR-VJPxw.png

最後连贯的画面如下
ydAW9hFA6ql

本篇的GitHub source code

下篇将为大家介绍 animated_text_kit


<<:  DAY 15 处理接收到的LINE emoji讯息

>>:  [Day 27] JS实作练习 - Music Player

Leftover topics

我们终於来到第廿九篇,我们这次讨论的题目都是之前讨论过的东西的延伸。因为篇幅和时间有限就只好把它们合...

30天学会Python: Day 26-一心多用

同步执行 目前写的程序都是一行接着一行一行执行,这种执行的方式叫做 同步执行 print("...

Ruby幼幼班--Rotate String

坚持传教K-pop...就可以坚持每天解题?? Rotate String 题目连结:https:...

【Day30】挑战回顾 & 铁人练成心得分享

挑战最後一日的题目真的让我想了很久,倒底该放什麽元件来压轴才好?要写一个综合演练,把前面的元件都拿出...