Android中如何自定义BarcodeDetector实现指定条码过滤高亮
Android Vision条码扫描器指定条码过滤高亮实现方案
你现有基于com.google.android.gms:play-services-vision:20.1.3的条码检测框架已经完成基础能力,要实现仓库找货场景下的指定条码过滤、高亮效果,不需要改动底层相机和检测逻辑,只需要修改覆盖层绘制、跟踪器状态标记、交互反馈三个模块即可。
具体实现步骤
1. 改造条码图形类,增加匹配状态区分
首先修改你自定义的BarcodeGraphic类,新增状态标记和两套绘制样式:
- 新增
boolean isTarget成员变量,标记当前条码实例是否为查找目标 - 定义两组画笔:非匹配条码用半透明细灰边(或者直接不绘制,避免干扰视线),匹配目标用粗亮绿色边框,额外加文字绘制能力显示匹配到的条码值
- 修改
draw(Canvas canvas)绘制逻辑,根据当前模式和isTarget状态选择对应画笔绘制:- 当处于找货模式(
fromWhere == "findInWarehouse"且传入了codeToCheck),非目标条码仅绘制极淡边框提示存在,或者直接跳过不绘制;目标条码用高亮样式绘制,同时在边框上方绘制条码文本方便确认 - 非找货模式保持原有逻辑,所有检测到的条码正常绘制即可
- 当处于找货模式(
2. 透传过滤参数到跟踪器,实时更新匹配状态
你现有初始化BarcodeTrackerFactory时仅传入了覆盖层和回调监听,需要把过滤规则一路透传到条码跟踪器:
- 给
BarcodeTrackerFactory新增两个构造参数:String targetCode(要查找的目标条码值)、boolean isFilterMode(是否开启过滤模式),在BarcodeCaptureActivity的createCameraSource()方法中初始化工厂时,把从Intent拿到的codeToCheck、模式判断值传入 - 工厂创建
BarcodeGraphicTracker实例时,把上述两个参数继续传入跟踪器 - 重写跟踪器的
onUpdate()方法,每帧检测到条码时先做值比对:注意比对前要对两边字符串做trim()去首尾空格,统一转大写/小写后再做相等判断,避免污渍、识别误差带来的空格、大小写问题导致匹配失败;把比对结果赋值给对应BarcodeGraphic的isTarget属性,最后调用覆盖层的postInvalidate()触发重绘
3. 优化交互逻辑,适配仓库作业场景
你现有匹配成功就播放提示音的逻辑会出现重复触发的问题,做几个针对性优化:
- 在Activity中新增
boolean hasFoundTarget = false标记,第一次检测到匹配条码时才播放成功提示音、触发震动,避免连续重复播报 - 匹配成功后不要立刻关闭相机,保持高亮状态2~3秒让操作人员确认货品,再自动返回结果,也可以加个屏幕确认按钮让用户手动触发返回
- 在扫描界面顶部固定显示当前查找的条码值,比如查找目标:3908181,避免操作人员记错目标
核心代码参考
BarcodeGraphic绘制逻辑修改
// 预定义画笔 private static final Paint NON_TARGET_PAINT = new Paint(); private static final Paint TARGET_BORDER_PAINT = new Paint(); private static final Paint TARGET_TEXT_PAINT = new Paint(); static { // 非目标条码:2px半透灰边 NON_TARGET_PAINT.setColor(Color.parseColor("#33888888")); NON_TARGET_PAINT.setStyle(Paint.Style.STROKE); NON_TARGET_PAINT.setStrokeWidth(2f); // 目标条码:6px亮绿粗边 TARGET_BORDER_PAINT.setColor(Color.parseColor("#FF00C853")); TARGET_BORDER_PAINT.setStyle(Paint.Style.STROKE); TARGET_BORDER_PAINT.setStrokeWidth(6f); // 目标条码文字 TARGET_TEXT_PAINT.setColor(Color.parseColor("#FF00C853")); TARGET_TEXT_PAINT.setTextSize(40f); TARGET_TEXT_PAINT.setFakeBoldText(true); } @Override public void draw(Canvas canvas) { Barcode barcode = getBarcode(); if (barcode == null) return; RectF bounds = getViewBoundingBox(); // 复用原有坐标转换逻辑获取条码在视图中的位置 if (isFilterMode) { if (isTarget) { canvas.drawRect(bounds, TARGET_BORDER_PAINT); canvas.drawText(barcode.displayValue, bounds.left, bounds.top - 24, TARGET_TEXT_PAINT); } else { // 不需要显示非目标条码直接注释下一行即可 canvas.drawRect(bounds, NON_TARGET_PAINT); } } else { // 普通模式复用原有绘制逻辑 canvas.drawRect(bounds, DEFAULT_BARCODE_PAINT); } }
跟踪器内条码匹配逻辑
@Override public void onUpdate(Detector.Detections<Barcode> detections, Barcode barcode) { super.onUpdate(detections, barcode); BarcodeGraphic graphic = getGraphicForBarcode(barcode); if (isFilterMode && !TextUtils.isEmpty(targetCode)) { String detectVal = barcode.displayValue.trim().toUpperCase(); String targetVal = targetCode.trim().toUpperCase(); boolean isMatch = detectVal.equals(targetVal); graphic.setIsTarget(isMatch); if (isMatch && !hasTriggeredCallback) { listener.onTargetMatched(barcode); hasTriggeredCallback = true; } } else { graphic.setIsTarget(false); } overlay.postInvalidate(); }
可选场景优化
- 给高亮的目标条码框加上下滚动的扫描线动画,在仓库光线较差的环境下更容易快速定位货品
- 支持模糊匹配规则:如果条码有污损导致部分字符识别错误,可以设置检测值包含目标字符串即判定匹配,降低漏识别概率
- 检测到目标后自动打开闪光灯常亮,方便操作人员核对货品标签信息
内容的提问来源于stack exchange,提问作者Mattia
相关产品推荐
相关产品推荐

