Flutter条码扫描插件famoco_scanner的使用

Flutter条码扫描插件famoco_scanner的使用

需求

  • 最低版本为Android 10 (API 28)。

兼容设备

兼容以下设备:

  • FX 325 (FX325,1)
  • FX 335 (FX335,1)

测试设备:

  • FX 335 (FX335,1)

使用方法

步骤1

在你的 MainActivity 中继承 FamocoScanPhysicalButtonHandlerActivity。如果你有更优的方法来处理物理按钮,可以忽略此步骤。

忽略此步骤也意味着 FamocoScanner.instance.scanPhysicalButton 将不会被调用。

步骤2

只需使用 FamocoScanner.instance。例如:

FamocoScanner.instance.startScan();

要拦截条形码,你只需要在 StatefulWidget 中使用 decodedComplete

[@override](/user/override)
void initState() {
    super.initState();
    _onDecodedSubscription = FamocoScanner.instance.decodedComplete.listen(
        (data) {
            setState(() {
                _lastBarcodeScanned = data.barcode;
            });
        });
}

[@override](/user/override)
void dispose() {
    super.dispose();
    _onDecodedSubscription.cancel();
}

当订阅到 decodedComplete 时,会自动调用 FamocoScanner.instance.enableScanner()。同样地,当取消订阅时,会自动调用 disableScanner

ℹ️ 实现实例会根据设备的品牌自动选择。

示例

你可以查看示例应用。

这是一个与SDK文档中的应用相同的示例:[Demo app (v1.3, source code)]。

完整示例代码

以下是完整的示例代码:

import 'dart:async';

import 'package:famoco_scanner/famoco_decoded_result.dart';
import 'package:famoco_scanner/famoco_physical_button_result.dart';
import 'package:famoco_scanner/famoco_scanner.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

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

  [@override](/user/override)
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  late final StreamSubscription<FamocoDecodedResult> _onDecodedSubscription;
  late final StreamSubscription<FamocoPhysicalButtonResult>
      _onPhysicalButtonSubscription;

  final _textEditingController = TextEditingController();

  String? _lastBarcodeScanned;
  ValueNotifier<bool> _fillEditTextOnFocus = ValueNotifier(false);
  bool _continousScanPhysicalButton = false;
  bool _nonStopScan = false;
  bool _scanning = false;

  [@override](/user/override)
  void dispose() {
    super.dispose();

    // 不要忘记这一步。
    _onDecodedSubscription.cancel();
    _onPhysicalButtonSubscription.cancel();

    _textEditingController.dispose();
    _fillEditTextOnFocus.removeListener(_fillEditTextOnFocusChanged);
  }

  void _fillEditTextOnFocusChanged() {
    FamocoScanner.instance.setOptions(
      onDecodedUseKeyboardEvents: _fillEditTextOnFocus.value,
    );
  }

  void _scanButtonPressed() {
    if (_scanning) {
      _startScan();
    } else {
      _stopScan();
    }
  }

  void _clearButtonPressed() {
    _lastBarcodeScanned = null;
    _fillEditTextOnFocus.value = false;
    _nonStopScan = false;
    _continousScanPhysicalButton = false;
    _scanning = false;
    _textEditingController.clear();

    setState(() {});
  }

  Widget _buildCheckbox(
    String text,
    bool value,
    ValueChanged<bool?>? onChanged,
  ) {
    return Row(
      children: [
        Checkbox(value: value, onChanged: onChanged),
        Expanded(
          child: Text(text),
        ),
      ],
    );
  }

  void _startScan() {
    setState(() {
      _scanning = true;
    });

    FamocoScanner.instance.startScan(isHandsFree: _nonStopScan);
  }

  void _stopScan() {
    setState(() {
      _scanning = false;
    });

    FamocoScanner.instance.stopScan();
  }

  [@override](/user/override)
  void initState() {
    super.initState();
    _onDecodedSubscription = FamocoScanner.instance.decodedComplete.listen(
      (data) {
        if (!_nonStopScan) {
          _stopScan();
        }

        _lastBarcodeScanned = data.barcode;

        setState(() {});
      },
    );

    _onPhysicalButtonSubscription =
        FamocoScanner.instance.scanPhysicalButton.listen((event) {
      if (event.isKeyDown) {
        if (!_continousScanPhysicalButton) {
          _startScan();
        }
      } else {
        if (_continousScanPhysicalButton && _scanning) {
          _startScan();
        } else {
          _stopScan();
        }
      }
    });

    _fillEditTextOnFocus.addListener(_fillEditTextOnFocusChanged);
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: SafeArea(
          child: Column(
            children: [
              Expanded(
                child: SingleChildScrollView(
                  child: Column(
                    children: [
                      Text(
                        '请扫描条形码',
                        style: Theme.of(context).textTheme.titleLarge,
                      ),
                      Container(
                        margin: const EdgeInsets.all(16),
                        child: Text(
                          _lastBarcodeScanned ?? '未扫描条形码',
                          style: Theme.of(context).textTheme.bodyMedium,
                        ),
                      ),
                      TextField(
                        controller: _textEditingController,
                      ),
                      _buildCheckbox(
                        '启用焦点填充编辑文本',
                        _fillEditTextOnFocus.value,
                        (value) {
                          setState(() {
                            _fillEditTextOnFocus.value = value ?? false;
                          });
                        },
                      ),
                      _buildCheckbox(
                        '连续扫描物理按钮',
                        _continousScanPhysicalButton,
                        (value) {
                          setState(() {
                            _continousScanPhysicalButton = value ?? false;
                          });
                        },
                      ),
                      _buildCheckbox(
                        '非停止扫描',
                        _nonStopScan,
                        (value) {
                          setState(() {
                            _nonStopScan = value ?? false;
                          });
                        },
                      ),
                    ],
                  ),
                ),
              ),
              Row(
                children: [
                  Expanded(
                    child: TextButton(
                      onPressed: _scanButtonPressed,
                      style: ButtonStyle(
                        backgroundColor: MaterialStateProperty.all(
                          _scanning ? Colors.red : Colors.green,
                        ),
                        foregroundColor:
                            MaterialStateProperty.all(Colors.white),
                      ),
                      child: Text(_scanning ? '停止' : '扫描'),
                    ),
                  ),
                  Expanded(
                    child: TextButton(
                      onPressed: _clearButtonPressed,
                      style: ButtonStyle(
                        backgroundColor: MaterialStateProperty.all(Colors.blue),
                        foregroundColor:
                            MaterialStateProperty.all(Colors.white),
                      ),
                      child: const Text('清除'),
                    ),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

更多关于Flutter条码扫描插件famoco_scanner的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter条码扫描插件famoco_scanner的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


famoco_scanner 是一个用于 Flutter 应用的条码扫描插件,它允许你在应用中集成条码扫描功能。以下是如何在 Flutter 项目中使用 famoco_scanner 插件的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 famoco_scanner 插件的依赖。

dependencies:
  flutter:
    sdk: flutter
  famoco_scanner: ^1.0.0  # 请使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入 famoco_scanner 插件。

import 'package:famoco_scanner/famoco_scanner.dart';

3. 初始化扫描器

在使用扫描功能之前,你需要初始化扫描器。

FamocoScanner scanner = FamocoScanner();

4. 启动扫描

你可以通过调用 startScan 方法来启动扫描。这个方法会返回一个 Future,你可以通过 await 来获取扫描结果。

String? barcode = await scanner.startScan();
if (barcode != null) {
  print("Scanned barcode: $barcode");
} else {
  print("Scan was cancelled or failed");
}

5. 处理扫描结果

扫描结果会以字符串的形式返回。你可以根据需要对扫描结果进行处理。

6. 释放资源

当不再需要扫描器时,应该释放资源。

scanner.dispose();

完整示例

以下是一个完整的示例,展示了如何在 Flutter 应用中使用 famoco_scanner 插件。

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ScannerScreen(),
    );
  }
}

class ScannerScreen extends StatefulWidget {
  [@override](/user/override)
  _ScannerScreenState createState() => _ScannerScreenState();
}

class _ScannerScreenState extends State<ScannerScreen> {
  final FamocoScanner scanner = FamocoScanner();
  String scannedBarcode = '';

  [@override](/user/override)
  void dispose() {
    scanner.dispose();
    super.dispose();
  }

  Future<void> scanBarcode() async {
    String? barcode = await scanner.startScan();
    if (barcode != null) {
      setState(() {
        scannedBarcode = barcode;
      });
    } else {
      setState(() {
        scannedBarcode = 'Scan failed or cancelled';
      });
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Barcode Scanner'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('Scanned Barcode: $scannedBarcode'),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: scanBarcode,
              child: Text('Scan Barcode'),
            ),
          ],
        ),
      ),
    );
  }
}
回到顶部