美文网首页Flutter圈子FlutterFlutter
Flutter自制插件之r_scan二维码&条形码扫描(支持文件

Flutter自制插件之r_scan二维码&条形码扫描(支持文件

作者: rhyme_lph | 来源:发表于2020-02-27 16:12 被阅读0次
    image

    介绍

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

    使用

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

    dependencies:
        r_scan: last version
    
    • last version 可以在pub.dev网站搜索r_scan得到

    各设备注意事项

    • Android平台下

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

    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文件下添加如下代码:

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

    导包

    import 'package:r_scan/r_scan.dart';
    

    1.扫描文件图片二维码

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

    2.扫描图片链接二维码

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

    3.扫描内存图片二维码

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

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

    • 步骤1:获取可用相机
    List<RScanCameraDescription> rScanCameras = await availableRScanCameras();;
    

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

    List<RScanCameraDescription> rScanCameras;
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      rScanCameras = await availableRScanCameras();
      runApp(...);
    }
    
    • 步骤2:开始使用
    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使用相机扫描二维码/条形码

    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类的实例直接调用

    //关闭闪光灯
    await _controller.setFlashMode(false);
    
    //打开闪光灯
    await _controller.setFlashMode(true);
    
    // 获取闪光灯状态
    bool isOpen = await _controller.getFlashMode();
    

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

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

    class RScanResult {
      /// 条形码类型
      final RScanBarType type;
    
      ///附带的信息
      final String message;
    
      ///条形码对应的区域 包含 [x , y] 坐标
      final List<RScanPoint> points;
    }
    

    后续开发

    1. 支持自定义区域触发扫描
    2. 还有更多...

    相关文章

      网友评论

        本文标题:Flutter自制插件之r_scan二维码&条形码扫描(支持文件

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