Flutter 最佳扫码插件——自定义视图

lxf2023-05-04 00:56:24

之前封装了Flutter扫码插件后,许多人希望能提供自定义视图的支持,于是将flutter_scankit 升级到v1.2。关于该插件的介绍以及基础用法,请查看上一篇《Flutter 最佳扫码插件》

自定义视图

使用插件库提供的ScanKitWidget作为扫码控件,建议用Stack布局组合其他控件实现自定义视图。

在创建ScanKitWidget时,必须实现其回调函数callback,该回调返回一个ScanKitController ,用于调用与扫码相关的功能。

	ScanKitWidget(
               callback: (controller) {
                 _controller = controller;
               },
	)

创建ScanKitWidget时,还有一些属性可以设置:

  • boundingBox:设置识码区域的位置大小

  • format:指定扫码的类型,不传默认为全部类型,与 startScan方法scanTypes参数相同,参考startScan

  • continuouslyScan:设置是否为连续扫码模式

以上属性的解释,可参考HUAWEI ScanKit 的 官方文档

ScanKitController 中包含如下方法:

  • getLightStatus():当前闪光灯是否开启
  • switchLight():切换闪光灯(on/off)
  • pickPhoto() :拉起图库,从图片识别二维码
  • dispose()
  • pauseContinuouslyScan()
  • resumeContinuouslyScan()

需要注意的是,pauseContinuouslyScan()resumeContinuouslyScan()仅Android平台支持,关于这两个方法的说明,请查看 这里

另外,ScanKitController onLightVisible 属性也是仅Android平台支持,它是判断环境光亮明暗的监听,返回值为布尔类型,true表示场景昏暗;false表示场景明亮。开发者可通过该监听实现自动开启闪光灯功能。

获取识码结果

监听ScanKitControlleronResult属性

		ScanKitWidget(
                callback: (controller) {
                  _controller = controller;

                  controller.onResult.listen((result) {
                  		debugPrint("scanning result:$result");
                  });
        },

完整示例

实现自定义视图:

class CustomizedView extends StatefulWidget {
  @override
  _CustomizedViewState createState() => _CustomizedViewState();
}

const boxSize = 200.0;

class _CustomizedViewState extends State<CustomizedView> {
  late ScanKitController _controller;

  final screenWidth = window.physicalSize.width;
  final screenHeight = window.physicalSize.height;
  
  @override
  void dispose(){
    _controller.dispose();
   super.dispose(); 
  }

  @override
  Widget build(BuildContext context) {
    var pixelSize = boxSize * window.devicePixelRatio;
    var left = screenWidth/2 - pixelSize/2;
    var top = screenHeight/2 - pixelSize/2;
    var right = screenWidth/2 + pixelSize/2;
    var bottom = screenHeight/2 + pixelSize/2;
    var rect = Rect.fromLTRB(left, top, right, bottom);

    return Scaffold(
      body: SafeArea(
        child: Stack(
          children: [
            ScanKitWidget(
                callback: (controller) {
                  _controller = controller;

                  controller.onResult.listen((result) {
                    debugPrint("scanning result:$result");

                    Navigator.of(context).pop(result);
                  });
                },
              continuouslyScan: false,
              boundingBox: rect),
            Align(
              alignment: Alignment.topCenter,
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  IconButton(
                      onPressed: () {
                        Navigator.of(context).pop();
                      },
                      icon: Icon(
                        Icons.arrow_back,
                        color: Colors.white,
                        size: 28,
                      )),
                  IconButton(
                      onPressed: () {
                        _controller.switchLight();
                      },
                      icon: Icon(
                        Icons.lightbulb_outline_rounded,
                        color: Colors.white,
                        size: 28,
                      )),
                  IconButton(
                      onPressed: () {
                        _controller.pickPhoto();
                      },
                      icon: Icon(
                        Icons.picture_in_picture_rounded,
                        color: Colors.white,
                        size: 28,
                      ))
                ],
              ),
            ),

            Align(
              alignment: Alignment.center,
              child: Container(
                width: boxSize,
                height: boxSize,
                decoration: BoxDecoration(
                  border: Border(
                      left: BorderSide(color: Colors.orangeAccent, width: 2),
                      right: BorderSide(color: Colors.orangeAccent, width: 2),
                      top: BorderSide(color: Colors.orangeAccent, width: 2),
                      bottom: BorderSide(color: Colors.orangeAccent, width: 2)),
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

拉起自定义视图:

  Future<void> newPage(BuildContext context) async {
    var code = await Navigator.of(context).push(MaterialPageRoute(
        builder: (BuildContext context) {
          return CustomizedView();
        }
    ));

    setState(() {
      this.code = code ?? "";
    });
  }

完整代码参见 Example

视频课程

希望系统学习Flutter应用开发,可以参加我的网校中的 《Flutter 全栈式开发指南》课程。

想学习Flutter插件开发,在我的网校中查看《Flutter全栈式开发-高级篇》课程,从零开始插件开发,包含Android/iOS原生基础,全网独家深入解析关于Flutter插件开发的方方面面,实战讲解多个案例(包含本插件开发过程)

本网站是一个以CSS、JavaScript、Vue、HTML为核心的前端开发技术网站。我们致力于为广大前端开发者提供专业、全面、实用的前端开发知识和技术支持。 在本网站中,您可以学习到最新的前端开发技术,了解前端开发的最新趋势和最佳实践。我们提供丰富的教程和案例,让您可以快速掌握前端开发的核心技术和流程。 本网站还提供一系列实用的工具和插件,帮助您更加高效地进行前端开发工作。我们提供的工具和插件都经过精心设计和优化,可以帮助您节省时间和精力,提升开发效率。 除此之外,本网站还拥有一个活跃的社区,您可以在社区中与其他前端开发者交流技术、分享经验、解决问题。我们相信,社区的力量可以帮助您更好地成长和进步。 在本网站中,您可以找到您需要的一切前端开发资源,让您成为一名更加优秀的前端开发者。欢迎您加入我们的大家庭,一起探索前端开发的无限可能!