Flutter开发 - 二维码扫描

3,149 阅读1分钟

Flutter开发 - 二维码扫描

项目开发中, 经常会用到二维码扫描, 而一个二维码扫描页面最常见的功能包括两点:

  • 二维码扫描
  • 扫描动画

二维码扫描

Flutter中, 二维码扫描需要与原生交互. 因此需要做对应的插件开发.

下面简单介绍下, 之前开发的一个二维码扫描插件.

qrcode

该插件, 在iOS中使用的AVCaptureSession, Android中使用的是zxing.

pub: pub.flutter-io.cn/packages/qr…

github: github.com/SiriDx/qrco…

添加依赖

在pubspec.yaml添加

dependencies:
  qrcode: ^1.0.2

安装

执行命令

flutter pub get

Import

import 'package:qrcode/qrcode.dart';

基本使用

  • QRCaptureView
// 扫描捕捉视图, 传入QRCaptureController对象
QRCaptureView(controller: _captureController)
  • QRCaptureController
// 获取扫描结果
_captureController.onCapture((data) {
      print('onCapture----$data');
});

// 恢复与暂停扫描
_captureController.resume();
_captureController.pause();

// 设置手电筒模式
_captureController.torchMode = CaptureTorchMode.off;
_captureController.torchMode = CaptureTorchMode.on;

示例

class _MyAppState extends State<MyApp> {
  QRCaptureController _captureController = QRCaptureController();

  bool _isTorchOn = false;

  @override
  void initState() {
    super.initState();

    _captureController.onCapture((data) {
      print('onCapture----$data');
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            QRCaptureView(controller: _captureController),
            Align(
              alignment: Alignment.bottomCenter,
              child: _buildToolBar(),
            )
          ],
        ),
      ),
    );
  }

  Widget _buildToolBar() {
    return Row(
          mainAxisSize: MainAxisSize.max,
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FlatButton(
              onPressed: () {
                _captureController.pause();
              },
              child: Text('pause'),
            ),
            FlatButton(
              onPressed: () {
                if (_isTorchOn) {
                  _captureController.torchMode = CaptureTorchMode.off;
                } else {
                  _captureController.torchMode = CaptureTorchMode.on;
                }
                _isTorchOn = !_isTorchOn;
              },
              child: Text('torch'),
            ),
            FlatButton(
              onPressed: () {
                _captureController.resume();
              },
              child: Text('resume'),
            ),
          ],
        );
  }
}

集成

iOS中, 需要在info.plist中添加以下内容, 并在<string></string>中填写请求相机权限的描述

<key>NSCameraUsageDescription</key>
<string>Camera permission is required for qrcode scanning.</string>
<key>io.flutter.embedded_views_preview</key>
<true/>

扫描动画

使用Tween实现来回扫描的动画

class _MyAppState extends State<MyApp> with TickerProviderStateMixin {

  Animation<Alignment> _animation;
  AnimationController _animationController;

  @override
  void initState() {
    super.initState();
    _animationController =
        AnimationController(vsync: this, duration: Duration(seconds: 1));
    _animation =
        AlignmentTween(begin: Alignment.topCenter, end: Alignment.bottomCenter)
            .animate(_animationController)
              ..addListener(() {
                setState(() {});
              })
              ..addStatusListener((status) {
                if (status == AnimationStatus.completed) {
                  _animationController.reverse();
                } else if (status == AnimationStatus.dismissed) {
                  _animationController.forward();
                }
              });
    _animationController.forward();
  }

  @override
  void dispose() {
    super.dispose();
    _animationController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          alignment: Alignment.center,
          children: <Widget>[
            QRCaptureView(
              controller: _captureController,
            ),
            Padding(
              padding: EdgeInsets.symmetric(horizontal: 56),
              child: AspectRatio(
                aspectRatio: 264 / 258.0,
                child: Stack(
                  alignment: _animation.value,
                  children: <Widget>[
                    Image.asset('images/sao@3x.png'),
                    Image.asset('images/tiao@3x.png')
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

在qrcode插件的example/lib/main中, 可以查看完整代码