前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter自制插件之r_scan二维码&条形码扫描(支持文件、url、内存、相机)

Flutter自制插件之r_scan二维码&条形码扫描(支持文件、url、内存、相机)

作者头像
rhyme_lph
发布2020-03-20 12:39:57
2.1K0
发布2020-03-20 12:39:57
举报
文章被收录于专栏:Flutter&Dart

介绍

二维码作为信息的载体,广泛应用于我们生活的方方面面,例如:使用支付宝支付,二维码加好友,二维码推广等等,能举例的例子多不胜数,而如果你的应用支持二维码的扫描,用户和体验将会翻倍的增长,如果你是应用的开发者,欢迎来使用此二维码扫描插件!并希望能给予项目一个star,谢谢!项目地址:https://github.com/rhymelph/r_scan

使用

你可以在pub.dev网站上面搜索r_scan即可找到该插件,添加下面代码到pubspec.yaml文件

代码语言:javascript
复制
dependencies:
    r_scan: last version
  • last version 可以在pub.dev网站搜索r_scan得到

各设备注意事项

  • Android平台下

android6.0系统以上请动态授权,可以结合permission_handler插件使用,代码如下:

代码语言:javascript
复制
import 'package:permission_handler/permission_handler.dart';

Future<bool> canReadStorage() async {
    if(Platform.isIOS) return true;
    var status = await PermissionHandler()
        .checkPermissionStatus(PermissionGroup.storage);
    if (status != PermissionStatus.granted) {
      var future = await PermissionHandler()
          .requestPermissions([PermissionGroup.storage]);
      for (final item in future.entries) {
        if (item.value != PermissionStatus.granted) {
          return false;
        }
      }
    } else {
      return true;
    }
    return true;
  }

Future<bool> canOpenCamera() async {
    var status =
        await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
    if (status != PermissionStatus.granted) {
      var future = await PermissionHandler()
          .requestPermissions([PermissionGroup.camera]);
      for (final item in future.entries) {
        if (item.value != PermissionStatus.granted) {
          return false;
        }
      }
    } else {
      return true;
    }
    return true;
  }
  • IOS平台下

需要在info.plist文件下添加如下代码:

代码语言:javascript
复制
    <key>NSCameraUsageDescription</key>
    <string>扫描二维码时需要使用您的相机</string>
    <key>NSPhotoLibraryUsageDescription</key>
    <string>扫描二维码时需要访问您的相册</string>
    <key>io.flutter.embedded_views_preview</key>
    <true/>

导包

代码语言:javascript
复制
import 'package:r_scan/r_scan.dart';

1.扫描文件图片二维码

代码语言:javascript
复制
final result=await RScan.scanImagePath('你的文件路径');
if(result.isNotEmpty){
    //result 为二维码内容
}

2.扫描图片链接二维码

代码语言:javascript
复制
final result=await RScan.scanImagePath('你的图片链接');
if(result.isNotEmpty){
    //result 为二维码内容
}

3.扫描内存图片二维码

代码语言:javascript
复制
ByteData data=await rootBundle.load('images/qrCode.png');
final result=await RScan.scanImageMemory(data.buffer.asUint8List());
if(result.isNotEmpty){
    //result 为二维码内容
}

4.(NEW)基于Texture使用相机扫描二维码/条形码

  • 步骤1:获取可用相机
代码语言:javascript
复制
List<RScanCameraDescription> rScanCameras = await availableRScanCameras();;

如果你在main()方法下获取可用相机,请使用下面代码

代码语言:javascript
复制
List<RScanCameraDescription> rScanCameras;

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  rScanCameras = await availableRScanCameras();
  runApp(...);
}
  • 步骤2:开始使用
代码语言:javascript
复制
class RScanCameraDialog extends StatefulWidget {
  @override
  _RScanCameraDialogState createState() => _RScanCameraDialogState();
}

class _RScanCameraDialogState extends State<RScanCameraDialog> {
  RScanCameraController _controller;
  bool isFirst = true;

  @override
  void initState() {
    super.initState();
    //判断当前是否有可用相机
    if (rScanCameras != null && rScanCameras.length > 0) {
    //初始化相机控制器,一般rScanCameras[0]为后置,rScanCameras[1]为前置摄像头
      _controller = RScanCameraController(
          rScanCameras[0], RScanCameraResolutionPreset.max)
        ..addListener(() {
        //监听扫码返回结果
          final result = _controller.result;
          if (result != null) {
            if (isFirst) {
            //如果扫描到二维码将结果返回到上一页
              Navigator.of(context).pop(result);
              isFirst = false;
            }
          }
        })
        ..initialize().then((_) {
        //初始化相机
          if (!mounted) {
            return;
          }
          setState(() {});
        });
    }
  }

  @override
  void dispose() {
    _controller?.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
  //判断是否有可用相机
    if (rScanCameras == null || rScanCameras.length == 0) {
      return Scaffold(
        body: Container(
          alignment: Alignment.center,
          child: Text('not have available camera'),
        ),
      );
    }
    //判断相机如果没有初始化,给它一个加载页面
    if (!_controller.value.isInitialized) {
      return Container();
    }
    //获取到相机
    return Scaffold(
      backgroundColor: Colors.black,
      body: Stack(
        children: <Widget>[
          ScanImageView(
            child: AspectRatio(
            //拿到相机的aspectRatio
              aspectRatio: _controller.value.aspectRatio,
              child: RScanCamera(_controller),
            ),
          ),
          //闪光灯
          Align(
              alignment: Alignment.bottomCenter,
              child: FutureBuilder(
                future: getFlashMode(),
                builder: _buildFlashBtn,
              ))
        ],
      ),
    );
  }
  //获取闪光灯是否打开
  Future<bool> getFlashMode() async {
    bool isOpen = false;
    try {
      isOpen = await _controller.getFlashMode();
    } catch (_) {}
    return isOpen;
  }

//构建闪光灯按钮
  Widget _buildFlashBtn(BuildContext context, AsyncSnapshot<bool> snapshot) {
    return snapshot.hasData
        ? Padding(
      padding:  EdgeInsets.only(bottom:24+MediaQuery.of(context).padding.bottom),
      child: IconButton(
          icon: Icon(snapshot.data ? Icons.flash_on : Icons.flash_off),
          color: Colors.white,
          iconSize: 46,
          onPressed: () {
            if (snapshot.data) {
              _controller.setFlashMode(false);
            } else {
              _controller.setFlashMode(true);
            }
            setState(() {});
          }),
    )
        : Container();
  }
}

5.(已弃用)基于PlatformView使用相机扫描二维码/条形码

代码语言:javascript
复制
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:r_scan/r_scan.dart';

class RScanDialog extends StatefulWidget {
  @override
  _RScanDialogState createState() => _RScanDialogState();
}

class _RScanDialogState extends State<RScanDialog> {
  RScanController _controller;

  @override
  void initState() {
    super.initState();
    initController();
  }
  bool isFirst=true;


  Future<void> initController() async {
    _controller = RScanController();
    _controller.addListener(() {//监听扫描到的二维码
      final result = _controller.result;
      if (result != null) {
        if(isFirst){
          Navigator.of(context).pop(result);
          isFirst=false;
        }
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        backgroundColor: Colors.black,
        body: FutureBuilder<bool>(
          future: canOpenCameraView(),
          builder: (BuildContext context, AsyncSnapshot<bool> snapshot) {
            if (snapshot.hasData && snapshot.data == true) {
              return ScanImageView(//这个为自己写的前景
                child: RScanView(
                  controller: _controller,
                ),
              );
            } else {
              return Container();
            }
          },
        ),
      ),
    );
  }

  Future<bool> canOpenCameraView() async {
    var status =
        await PermissionHandler().checkPermissionStatus(PermissionGroup.camera);
    if (status != PermissionStatus.granted) {
      var future = await PermissionHandler()
          .requestPermissions([PermissionGroup.camera]);
      for (final item in future.entries) {
        if (item.value != PermissionStatus.granted) {
          return false;
        }
      }
    } else {
      return true;
    }
    return true;
  }
}

6. 打开闪光灯/获取闪光灯状态

使用RScanController类的实例直接调用

代码语言:javascript
复制
//关闭闪光灯
await _controller.setFlashMode(false);

//打开闪光灯
await _controller.setFlashMode(true);

// 获取闪光灯状态
bool isOpen = await _controller.getFlashMode();

7.RScanResult(二维码扫描结果)

当扫描到二维码&条形码将返回该对象,包含如下内容

代码语言:javascript
复制
class RScanResult {
  /// 条形码类型
  final RScanBarType type;

  ///附带的信息
  final String message;

  ///条形码对应的区域 包含 [x , y] 坐标
  final List<RScanPoint> points;
}

后续开发

  1. 支持自定义区域触发扫描
  2. 还有更多...
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 使用
      • 各设备注意事项
        • 导包
          • 1.扫描文件图片二维码
            • 2.扫描图片链接二维码
              • 3.扫描内存图片二维码
                • 4.(NEW)基于Texture使用相机扫描二维码/条形码
                  • 5.(已弃用)基于PlatformView使用相机扫描二维码/条形码
                    • 6. 打开闪光灯/获取闪光灯状态
                      • 7.RScanResult(二维码扫描结果)
                        • 后续开发
                        相关产品与服务
                        领券
                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档