flutter开发实战-flutter二维码条形码扫一扫功能实现

news2024/11/23 17:04:15

flutter开发实战-flutter二维码条形码扫一扫功能实现

flutter开发实战-flutter二维码扫一扫功能实现,要使用到摄像头的原生的功能,使用的是插件:scan

效果图如下

在这里插入图片描述

一、扫一扫插件scan

  # 扫一扫
  scan: ^1.6.0

1.1 iOS权限设置

<key>NSCameraUsageDescription</key>
<string>Your Description</string>

<key>io.flutter.embedded_views_preview</key>
<string>YES</string>

1.2 android权限设置

<uses-permission android:name="android.permission.CAMERA" />

<application>
  <meta-data
    android:name="flutterEmbedding"
    android:value="2" />
</application>

1.3 使用ScanView的widget

ScanController controller = ScanController();
String qrcode = 'Unknown';

Container(
  width: 250, // custom wrap size
  height: 250,
  child: ScanView(
    controller: controller,
// custom scan area, if set to 1.0, will scan full area
    scanAreaScale: .7,
    scanLineColor: Colors.green.shade400,
    onCapture: (data) {
      // do something
    },
  ),
),

扫一扫Widget使用ScanController来做响应的控制

暂停/恢复camera

controller.pause();
controller.resume();

识别图片的二维码结果

String result = await Scan.parse(imagePath);

闪光灯切换

controller.toggleTorchMode();

二、代码实现

实现自定义扫码的appBar

class QrScanAppBar extends StatefulWidget {
  const QrScanAppBar({
    Key? key,
    required this.toolbarHeight,
    this.elevation,
    this.backgroundColor,
    this.leadingWidget,
    this.trailingWidget,
    this.centerWidget,
    this.brightness,
    this.padding, this.barPadding,
  }) : super(key: key);

  final double toolbarHeight;
  final double? elevation;
  final Color? backgroundColor;
  final Widget? leadingWidget;
  final Widget? trailingWidget;
  final Widget? centerWidget;
  final Brightness? brightness;
  final EdgeInsetsGeometry? padding;
  final EdgeInsetsGeometry? barPadding;

  
  State<QrScanAppBar> createState() => _QrScanAppBarState();
}

class _QrScanAppBarState extends State<QrScanAppBar> {
  
  Widget build(BuildContext context) {
    final SystemUiOverlayStyle overlayStyle =
        widget.brightness == Brightness.dark
            ? SystemUiOverlayStyle.light
            : SystemUiOverlayStyle.dark;

    Widget leadingWidget = (widget.leadingWidget ?? Container());
    Widget centerWidget = (widget.centerWidget ?? Container());
    Widget trailingWidget = (widget.trailingWidget ?? Container());

    return AnnotatedRegion<SystemUiOverlayStyle>(
      //套AnnotatedRegion是为了增加状态栏控制
      value: overlayStyle,
      child: Material(
        //套Material是为了增加elevation
        elevation: widget.elevation ?? 0,
        color: Colors.transparent,
        child: Container(
          padding: widget.padding,
          height: widget.toolbarHeight + ScreenUtil().statusBarHeight,
          decoration: BoxDecoration(
            color: widget.backgroundColor,
          ),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                height: ScreenUtil().statusBarHeight,
              ),
              Expanded(
                child: Container(
                  padding: widget.barPadding,
                  height: widget.toolbarHeight,
                  alignment: Alignment.center,
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Container(
                        height: widget.toolbarHeight,
                        child: leadingWidget,
                      ),
                      Expanded(
                        child: Container(
                          alignment: Alignment.center,
                          height: widget.toolbarHeight,
                          child: centerWidget,
                        ),
                      ),
                      Container(
                        height: widget.toolbarHeight,
                        child: trailingWidget,
                      ),
                    ],
                  ),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

实现扫一扫界面

class QrScanPage extends StatefulWidget {
  const QrScanPage({Key? key, this.arguments}) : super(key: key);

  final Object? arguments;

  
  State<QrScanPage> createState() => _QrScanPageState();
}

class _QrScanPageState extends State<QrScanPage> {
  ScanController scanController = ScanController();
  String qrcode = 'Unknown';
  bool torchOn = false;

  
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  
  void dispose() {
    // TODO: implement dispose
    scanController.pause();
    super.dispose();
  }

  void changedTorchMode() {
    scanController.toggleTorchMode();
    if (torchOn == true) {
      torchOn = false;
    } else {
      torchOn = true;
    }
    setState(() {});
  }

  void refreshScan() {
    scanController.resume();
  }

  // controller.resume();
  // controller.pause();
  // String result = await Scan.parse(imagePath);

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          buildQrScanView(context),
          Positioned(
            child: buildAppBar(context),
          ),
        ],
      ),
    );
  }

  Widget buildQrScanView(BuildContext context) {
    double width = MediaQuery.of(context).size.width;
    double height = MediaQuery.of(context).size.height;

    double scanW = width * 0.75;
    double scanMY = (height - scanW) / 2.0 + scanW + 15.0;

    return Container(
          alignment: Alignment.center,
          child: Stack(
            alignment: Alignment.center,
            children: [
              ScanView(
                controller: scanController,
                // custom scan area, if set to 1.0, will scan full area
                scanAreaScale: 0.75,
                scanLineColor: Colors.green.shade400,
                onCapture: (data) {
                  // do something
                  LoggerManager().debug("onCapture:${data}");
                  openQrScanWebPage(data);
                },
              ),
              Positioned(
                top: scanMY,
                child: buildOption(context, scanMY),
              ),
            ],
          ),
        );
  }

  Widget buildAppBar(BuildContext context) {
    return QrScanAppBar(
      toolbarHeight: 44.0,
      backgroundColor: Colors.transparent,
      padding: EdgeInsets.symmetric(horizontal: 10.0),
      barPadding: EdgeInsets.symmetric(vertical: 4.0),
      leadingWidget: Container(
        alignment: Alignment.center,
        child: QrscanButton(
          bgColor: ColorUtil.hexColor(0xA9A9A9),
          bgHighlightedColor: ColorUtil.hexColor(0xf0f0f0),
          borderColor: Colors.transparent,
          onPressed: () {
            navigatorBack();
          },
          borderRadius: 18.0,
          height: 36.0,
          width: 36.0,
          child: ImageHelper.wrapAssetAtImages(
            "icons/ic_scan_navback.png",
            width: 36.0,
            height: 36.0,
            fit: BoxFit.fill,
          ),
        ),
      ),
      centerWidget: Text(
        S.of(context).qrScan,
        textAlign: TextAlign.center,
        softWrap: true,
        style: TextStyle(
          fontSize: 17,
          color: ColorUtil.hexColor(0xffffff),
          fontWeight: FontWeight.w600,
          fontStyle: FontStyle.normal,
          decoration: TextDecoration.none,
        ),
      ),
      trailingWidget: Container(
        width: 32.0,
        height: 32.0,
      ),
    );
  }

  Widget buildOption(BuildContext context, double originY) {
    return Container(
      height: ScreenUtil().screenHeight - originY,
      width: ScreenUtil().screenWidth,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          Container(
            width: 300.0,
            child: Text(
              S.of(context).qrScanBottomTip,
              textAlign: TextAlign.center,
              softWrap: true,
              style: TextStyle(
                fontSize: 15,
                fontWeight: FontWeight.w500,
                fontStyle: FontStyle.normal,
                color: Colors.white,
                decoration: TextDecoration.none,
              ),
            ),
          ),
          SizedBox(
            height: 25.0,
          ),
          buildButtons(context),
          Expanded(
            child: Container(),
          ),
        ],
      ),
    );
  }

  Widget buildButtons(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 20.0),
          child: QrscanButton(
            bgColor: ColorUtil.hexColor(0x35fb99),
            bgHighlightedColor: Colors.green.shade400,
            onPressed: () {
              changedTorchMode();
            },
            width: 100.0,
            height: 50.0,
            borderRadius: 25.0,
            child: Text(
              (torchOn
                  ? S.of(context).qrScanTorchOff
                  : S.of(context).qrScanTorchOn),
              textAlign: TextAlign.center,
              softWrap: true,
              style: TextStyle(
                fontSize: 14,
                color: ColorUtil.hexColor(0xffffff),
                fontWeight: FontWeight.w600,
                fontStyle: FontStyle.normal,
                decoration: TextDecoration.none,
              ),
            ),
          ),
        ),
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 20.0),
          child: QrscanButton(
            bgColor: ColorUtil.hexColor(0x35fb99),
            bgHighlightedColor: Colors.green.shade400,
            onPressed: () {
              refreshScan();
            },
            width: 100.0,
            height: 50.0,
            borderRadius: 25.0,
            child: Text(
              S.of(context).qrScanRefresh,
              textAlign: TextAlign.center,
              softWrap: true,
              style: TextStyle(
                fontSize: 14,
                color: ColorUtil.hexColor(0xffffff),
                fontWeight: FontWeight.w600,
                fontStyle: FontStyle.normal,
                decoration: TextDecoration.none,
              ),
            ),
          ),
        ),
      ],
    );
  }

  void navigatorBack() {
    NavigatorPageRouter.pop();
  }

  void openQrScanWebPage(String data) {
    Map<String, dynamic> args = {};
    args["url"] = data;

    /// true保留跳转的当前栈   false 不保留
    NavigatorPageRouter.pushReplacementNamed(
      RouterName.web,
      arguments: args,
    );
  }
}

三、小结

flutter开发实战-flutter二维码扫一扫功能实现,要使用到摄像头的原生的功能,使用的是插件:scan,实现自定义Appbar。

学习记录,每天不停进步。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/751285.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移动互联网时代的网络口碑营销怎么做

从人类开始交换商品的时代开始&#xff0c;口碑营销就已经存在&#xff0c;是靠口耳传播的营销方式。小马识途认为进入当今移动互联网时代&#xff0c;口碑营销又有了新的发展&#xff0c;网络口碑营销推广开始普及。营销人员将传统口碑营销与移动互联网营销相结合&#xff0c;…

在arm平台上安装qt

qt官网上如果没有找到对应的安装包&#xff0c;就需要下载源代码自行编译安装qt&#xff0c;时间会久一点 qt下载 进入官网下载 如下图步骤选择源代码包&#xff08;以5.12.12为例&#xff09; 可以复制链接地址在迅雷上创建下载任务&#xff0c;下载速度会快些 qt的编译与…

基于Javaweb实现ATM机系统开发实战(十)取款功能实现

老规矩&#xff0c;先看前端页面&#xff1a; <% page language"java" contentType"text/html; charsetUTF-8" pageEncoding"UTF-8"%> <% taglib prefix"c" uri"http://java.sun.com/jsp/jstl/core" %> <!D…

B069-项目实战-店铺入驻-FastDfs-邮件

目录 店铺入驻课堂笔记data表结构自定义业务异常impl 图片上传-fastdfs应用背景概念理论入门案例项目使用1.导包2.添加配置文件3.导入工具类4.写接口将工具类暴露给前端使用5.前端部分 审核邮件通知1.导入jar包2.配置3.发送邮件邮件激活登录账号 店铺入驻 到平台来注册店铺信息…

Anaconda详细安装和使用

文章目录 Anaconda简介下载安装官网清华镜像 环境变量配置使用pip配置清华镜像下载路径创建新的虚拟环境进入新的虚拟环境在新环境下载需要的依赖包删除虚拟环境&#xff08;依赖包&#xff09; Anaconda 简介 Anaconda是一个用于科学计算和数据分析的开源Python发行版本.它提…

HLS(一)Vivado高层次综合概述

目录 1.什么是FPGA&#xff1f; 1.1 简介 1.2 架构 1.3 FPGA并行方式与处理器对比 2.硬件设计基本概念 2.1 时钟频率 2.2 延迟 2.3 吞吐率 2.4 存储布局 3.高层次综合 3.1 概述 3.2 运算 ​3.3 条件语句 3.3循环 3.5 函数 3.6 动态内存申请 3.7 指针 4.以计算…

Python应用:打造一个简单的爬虫

文章目录 爬虫基本步骤如何发起网页请求requests的安装requests的使用 如何解析拿到的HTML反爬虫与反反爬虫机制进阶http请求头User-Agent 参考文献 爬虫基本步骤 对于一般的爬虫而言&#xff0c;其基本步骤&#xff1a; 找到需要爬取内容的网页URL&#xff1b;打开该网页的检…

【DBA课程-笔记】第 3 章:MongoDB数据库核心知识

内容 一、MongoDB 数据库架构 A. MongoDB数据库体系架构 1. 存储引擎&#xff08;MongoDB Storage Engines&#xff09;&#xff1a; 2. MongoDB 数据逻辑架构 二、MongoDB 存储引擎 A. 查看mongodb服务器的状态 B. 查看引擎信息&#xff08;4.2.1 没有这个命令&#xf…

数据结构(王道)——顺序表的定义

线性表和顺序表的关系&#xff1a; 两种实现方式&#xff1a;静态分配、动态分配 总结&#xff1a;

Node.js 版本管理工具 n 使用指南

Node.js 版本更新很快&#xff0c;目前 node v20.x 已经发布&#xff0c;我们在使用时避免不了会需要切换不同的 Node.js 的版本来使用不同版本的特性。 所以就出现了像 windows 上的 nvm&#xff0c;MacOS 上的 n 工具&#xff0c;本文就介绍一下如何使用 n 管理 Node.js 的版…

Linux专栏(一)——VMware的下载与安装

一、背景 想要学习Linux系统但又不想经历安装双系统复杂的操作&#xff0c;可以试试虚拟机方案。只是虚拟机方案不可以调用GPU就非常的无语&#xff0c;作为初学者学习还是非常不错的&#xff01; 注意&#xff1a;倘若真正转入Linux系统&#xff0c;安装双系统或者单Linux才是…

Vue2配置在methods中的方法属性丢失

Vue2配置在methods中的方法属性丢失 需求 现在有这样一个需求&#xff1a;一个带有搜索建议的搜索框&#xff0c;搜索建议由后端数据请求回来。当搜索框失去焦点时&#xff0c;应该取消搜索&#xff0c;直接使用输入的内容。 实现 实现原理为防抖加取消&#xff1a; //deb…

小程序 wxchart 使用简单入门

官方参考&#xff1a; Example - wxCharts使用说明 Issue #58 xiaolin3303/wx-charts GitHub 引入 地址&#xff1a;GitHub - xiaolin3303/wx-charts: 微信小程序图表charts组件&#xff0c;Charts for WeChat Mini Program 把clone下来的文件里dist下面的wxcharts.js或…

快手直播间数据采集截流软件脚本,实时采集引流精准获取客源【采集脚本+引流技术教程】

脚本功能&#xff1a;可查观众的块手号&#xff0c;二维码&#xff0c;主页&#xff0c;实时的弹幕消息&#xff0c;以及直播间送出的礼物&#xff0c;实时切换榜首的信息。​ 设备需求&#xff1a;电脑 文章的来源&#xff1a;ZZZZ.LA 文章分享者&#xff1a;Linxiaoyu2022 文…

Python微实践 - 诗意书香,宋风雅韵

诗意书香&#xff0c;宋风雅韵&#xff0c;宋代的文人们或婉约&#xff0c;或豪放&#xff0c;为后世留下了不朽的文学遗产 —— 宋词。宋词本质上是用于合乐的歌词&#xff0c;词人在填词时用的曲调名即为词牌。各位读者在中学时期一定对“水调歌头”、“念奴娇”这些词牌名耳…

mybatis-plus 实现自动填充

文章目录 1、自定义实现类 MyMetaObjectHandler2、在entity中标记需要自动填充的属性3、FieldFill中有哪些字段 1、自定义实现类 MyMetaObjectHandler import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import lombok.extern.slf4j.Slf4j; import org.apach…

【Python】PyCharm中调用另一个文件的函数或类

&#x1f389;欢迎来到Python专栏~PyCharm中调用另一个文件的函数或类 ☆* o(≧▽≦)o *☆嗨~我是小夏与酒&#x1f379; ✨博客主页&#xff1a;小夏与酒的博客 &#x1f388;该系列文章专栏&#xff1a;Python学习专栏 文章作者技术和水平有限&#xff0c;如果文中出现错误&…

SOKIT软件的使用

1.模拟客户端向服务器发送报文 客户端---->TCP连接---->填写数据----->点击“发送” 2.模拟服务器接受报文 服务器---->设置IP地址与端口---->点击TCP侦听 就可以往该地址发送报文信息了

需求分析案例:全局错误码设计

本文介绍了我在一些业务系统中遇到的错误提示问题&#xff0c;以及进行需求分析和设计实现的过程&#xff0c;欢迎进行交流和指点&#xff0c;一起进步。 1、需求起源 作为程序员&#xff0c;或多或少&#xff0c;都经历过如下场景&#xff1a; 场景1&#xff1a; 产品经理&a…

Stable Diffusion 用2D图片制作3D动态壁纸

如果想让我们的2D图片动起来可以使用stable-diffusion-webui-depthmap-script插件在SD中进行加工让图片动起来。 这是一个可以从单个图像创建深度图,现在也可以生成3D立体图像对的插件,无论是并排还是浮雕。生成的结果可在3D或全息设备(如VR耳机或Looking Glass显示器)上查…