You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Flutter制作带自定义聚焦边框的二维码扫描器

Flutter 实现带聚焦边框的内嵌式二维码扫描器方案

你当前使用的flutter_barcode_scanner包调用的是原生全屏扫描页面,不支持自定义内嵌视图和扫描边框,要实现Container内运行、带蓝色聚焦边框的效果,推荐使用支持高度自定义的mobile_scanner包实现,步骤如下:

1. 添加依赖

在pubspec.yaml中添加依赖:

dependencies:
  flutter:
    sdk: flutter
  mobile_scanner: ^3.5.5 # 可替换为最新稳定版

执行flutter pub get安装依赖。

2. 实现带自定义边框的扫描页面

核心逻辑是将扫描视图放在指定大小的Container内,上层叠加自定义的蓝色聚焦边框层,完整代码示例:

import 'package:flutter/material.dart';
import 'package:mobile_scanner/mobile_scanner.dart';

class QrScannerPage extends StatefulWidget {
  const QrScannerPage({super.key});

  @override
  State<QrScannerPage> createState() => _QrScannerPageState();
}

class _QrScannerPageState extends State<QrScannerPage> {
  final MobileScannerController _scannerController = MobileScannerController(
    formats: [BarcodeFormat.qrCode], // 只识别二维码
    autoStart: true,
  );

  // 处理扫码结果
  void _handleScanResult(BarcodeCapture capture) {
    final List<Barcode> barcodes = capture.barcodes;
    if (barcodes.isNotEmpty) {
      final String qrCode = barcodes.first.rawValue ?? '';
      // 扫码成功后停止扫描
      _scannerController.stop();
      if (!mounted) return;
      // 弹出结果弹窗,和你原有逻辑一致
      showDialog(
        context: context,
        builder: (_) {
          return Dialog(
            shape: RoundedRectangleBorder(
              borderRadius: BorderRadius.circular(10),
            ),
            child: Container(
              height: 300,
              width: 250,
              padding: const EdgeInsets.all(20),
              child: Center(child: Text(qrCode)),
            ),
          );
        },
      ).then((_) {
        // 关闭弹窗后返回上一页
        Navigator.pop(context);
      });
    }
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      appBar: AppBar(
        title: const Text('扫码'),
        backgroundColor: Colors.white,
        elevation: 0,
      ),
      body: Center(
        // 你要求的扫描功能运行在Container内,可自定义Container大小
        child: Container(
          width: 300,
          height: 300,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.transparent),
            borderRadius: BorderRadius.circular(12),
          ),
          clipBehavior: Clip.hardEdge,
          child: Stack(
            alignment: Alignment.center,
            children: [
              // 扫描视图层
              MobileScanner(
                controller: _scannerController,
                onDetect: _handleScanResult,
              ),
              // 蓝色聚焦边框层
              _buildScannerBorder(),
            ],
          ),
        ),
      ),
    );
  }

  // 自定义蓝色四角扫描边框
  Widget _buildScannerBorder() {
    const borderColor = Colors.blue;
    const borderWidth = 3.0;
    const borderRadius = 8.0;
    const borderLength = 24.0;

    return Stack(
      children: [
        // 左上角
        Positioned(
          top: 0,
          left: 0,
          child: Container(
            width: borderLength,
            height: borderLength,
            decoration: const BoxDecoration(
              border: Border(
                top: BorderSide(color: borderColor, width: borderWidth),
                left: BorderSide(color: borderColor, width: borderWidth),
              ),
              borderRadius: BorderRadius.only(topLeft: Radius.circular(borderRadius)),
            ),
          ),
        ),
        // 右上角
        Positioned(
          top: 0,
          right: 0,
          child: Container(
            width: borderLength,
            height: borderLength,
            decoration: const BoxDecoration(
              border: Border(
                top: BorderSide(color: borderColor, width: borderWidth),
                right: BorderSide(color: borderColor, width: borderWidth),
              ),
              borderRadius: BorderRadius.only(topRight: Radius.circular(borderRadius)),
            ),
          ),
        ),
        // 左下角
        Positioned(
          bottom: 0,
          left: 0,
          child: Container(
            width: borderLength,
            height: borderLength,
            decoration: const BoxDecoration(
              border: Border(
                bottom: BorderSide(color: borderColor, width: borderWidth),
                left: BorderSide(color: borderColor, width: borderWidth),
              ),
              borderRadius: BorderRadius.only(bottomLeft: Radius.circular(borderRadius)),
            ),
          ),
        ),
        // 右下角
        Positioned(
          bottom: 0,
          right: 0,
          child: Container(
            width: borderLength,
            height: borderLength,
            decoration: const BoxDecoration(
              border: Border(
                bottom: BorderSide(color: borderColor, width: borderWidth),
                right: BorderSide(color: borderColor, width: borderWidth),
              ),
              borderRadius: BorderRadius.only(bottomRight: Radius.circular(borderRadius)),
            ),
          ),
        ),
      ],
    );
  }
}

3. 替换原有扫码触发逻辑

把你原来调用scanQRCode方法的逻辑替换为跳转至QrScannerPage即可:

// 原来触发扫码的按钮点击事件修改为
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => const QrScannerPage()))

内容的提问来源于stack exchange,提问作者samit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 15:18:04