美文网首页
Flutter二维码扫描 2023-01-28 周六

Flutter二维码扫描 2023-01-28 周六

作者: 松哥888 | 来源:发表于2023-01-28 14:52 被阅读0次

简介

当前二维码扫描功能越来越普遍。在iOS原生,可以使用AVFoundation种的AVCapture相关的API进行自定义。
在Flutter层面,稍微想想就知道,Dart直接支持有点远,应该是需要通过插件的方式来实现。

插件选择

  • 自己写插件,理论上是可以的。iOS的应该可以继续用AVCapture来做。安卓的应该也有对应的实现方案。
    二维码扫描这个功能目前已经很普遍了,应该有三方插件可用。
    自己造轮子,还是使用现有的轮子?大多数人的选择应该是不言而喻的。

  • 进入Pub官网,输入scan关键字:

企业微信截图_94a7e1ab-2911-4470-bef5-c3895d1328f8.png

可以3个都看看,当然,也可以按照指标,直接选最多的那个qr_code_scanner
如果不在意指标,很有可能会选第3个mobile_scanner。虽然没有提供例子图片,但是其介绍中提到其实现方式都是系统原生的;不像第1个,原生实现都是采用了不再更新的第三方库。

  • 集成命令(这里是根据指标选的第1个):
flutter pub add qr_code_scanner

样例讨论

官网的Readme部分给出了一个例子,照抄可以用。这里给出一些不一样的思考。

热重载

  // In order to get hot reload to work we need to pause the camera if the platform
  // is android, or resume the camera if the platform is iOS.
  @override
  void reassemble() {
    super.reassemble();
    if (Platform.isAndroid) {
      controller!.pauseCamera();
    } else if (Platform.isIOS) {
      controller!.resumeCamera();
    }
  }
  • 这段代码特意加了注释,就是说想要flutter的热重载特性,就要重写State的reassemble方法,对相机进行复位。

  • 考虑到扫码是一次性的动作,需要热重载吗?大多数的场景就是打开一个页面,对着二维码扫描,成功后退出扫描页面,返回扫描到的字符串。所以,热重载是个鸡肋,不要更好。

扫描视图

  • 直接使用QRView就可以了,放在body中,默认就是全屏的。不需要放入Expanded中。

  • 默认是没有浮层的。想要浮层,给overlay参数赋值QrScannerOverlayShape()就可以了。
    浮层的样式,可以通过QrScannerOverlayShape()的参数调整。

扫描结果

  • 这个有点绕:首先,通过onQRViewCreated参数,把内部的QRViewController引出来;然后QRViewController建立侦听,在侦听的回调函数中,把扫描结果包装成Barcode对象给出。一般扫描的结果取barcode.code就可以了。
void _onQRViewCreated(QRViewController controller) {
    controller.scannedDataStream.listen((scanData) {
      setState(() {
        result = scanData;
      });
    });
  }
  • Demo中把QRViewController和Barcode保存起来,进行界面更新,其实没有必要。相机只有一个,初始化相机,关闭相机都是很费资源的操作。这个跟Flutter更新一次就重绘一次界面格格不入。所以,扫描界面还是做成stateless的无状态widget比较好。setState很昂贵,最好不要用。

资源回收

QRViewController由QRView创建,通过onQRViewCreated暴露出来,但是dispose方法需要使用者来调用。

权限管理

  • QRView通过onPermissionSet参数来进行权限管理。比如模拟器就没有摄像头,onPermissionSet会通过回调的bool类型参数设置为false来告诉使用者。

  • 最简单的处理方法就是直接退出扫描界面,然后toast提示一下就好了。

扫描结果去重

  • QRViewController侦听函数会返回多个扫描结果。下面的例子代码setState会执行多次,导致不可预料的结果。
    controller.scannedDataStream.listen((scanData) {
      setState(() {
        result = scanData;
      });
    });
  • 最直接能想到的就是用一个bool变量控制,只执行一次。

  • 另外一种方法,就是QRViewController的pauseCamera方法。取到一次结果之后,就停止扫描,这样能防止多重结果带来的不确定性。

参考代码

  /// 页面结构
  Widget _buildBody() {
    return QRView(
      key: GlobalKey(debugLabel: 'QR'),
      overlay: QrScannerOverlayShape(),
      onQRViewCreated: (qrViewController) {
        qrViewController.scannedDataStream.listen((barcode) {
          String code = barcode.code ?? '';
          if (code.isNotEmpty) {
            qrViewController.pauseCamera();
            EasyLoading.showInfo(code, duration: const Duration(seconds: 5));
            qrViewController.dispose();
            Get.back(result: code);
          }
        });
      },
      onPermissionSet: (qrViewController, isPermission) {
        if (!isPermission) {
          EasyLoading.showInfo('no permission');
          qrViewController.dispose();
          Get.back();
        }
      },
    );
  }

其他功能

相机相关的功能都包含在QRViewController中,比如火炬灯光,切换前后摄像头等。

相关文章

网友评论

      本文标题:Flutter二维码扫描 2023-01-28 周六

      本文链接:https://www.haomeiwen.com/subject/hryehdtx.html