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

Android项目使用ZXing生成带下方数字的EAN-8条码问题

解决ZXing生成EAN-8条码不显示下方数字的问题

嘿,我之前也踩过这个坑!你现在的代码只是把ZXing生成的条码点阵转成了黑白位图,ZXing的核心编码逻辑本身不会自动添加条码下方的文本,得我们自己手动补上绘制步骤才行。

下面是修改后的encodeAsBitmap方法,我已经加好了绘制条码数字的逻辑,直接替换你原来的方法就能用:

private static final int BLACK = 0xFF000000;
private static final int WHITE = 0xFFFFFFFF;

// 转dp为像素,保证文本区域在不同设备上高度一致
private int getTextAreaHeight(Context context) {
    return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources().getDisplayMetrics());
}

Bitmap encodeAsBitmap(String contents, BarcodeFormat format, int img_width, int img_height, Context context) throws WriterException {
    String contentsToEncode = contents;
    if (contentsToEncode == null) {
        return null;
    }
    Map<EncodeHintType, Object> hints = null;
    String encoding = guessAppropriateEncoding(contentsToEncode);
    if (encoding != null) {
        hints = new EnumMap<>(EncodeHintType.class);
        hints.put(EncodeHintType.CHARACTER_SET, encoding);
    }
    MultiFormatWriter writer = new MultiFormatWriter();
    BitMatrix result;
    try {
        result = writer.encode(contentsToEncode, format, img_width, img_height, hints);
    } catch (IllegalArgumentException iae) {
        // 不支持的格式
        return null;
    }
    int width = result.getWidth();
    int height = result.getHeight();
    int[] pixels = new int[width * height];
    for (int y = 0; y < height; y++) {
        int offset = y * width;
        for (int x = 0; x < width; x++) {
            pixels[offset + x] = result.get(x, y) ? BLACK : WHITE;
        }
    }
    Bitmap barcodeBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
    barcodeBitmap.setPixels(pixels, 0, width, 0, 0, width, height);

    // --- 新增:绘制条码下方的数字 ---
    int textAreaHeight = getTextAreaHeight(context);
    // 创建更大的Bitmap,预留文本显示空间
    Bitmap finalBitmap = Bitmap.createBitmap(width, height + textAreaHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(finalBitmap);
    // 先把原条码绘制到新Bitmap的顶部
    canvas.drawBitmap(barcodeBitmap, 0, 0, null);

    // 设置文本画笔样式
    Paint textPaint = new Paint();
    textPaint.setColor(BLACK);
    textPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 16, context.getResources().getDisplayMetrics()));
    textPaint.setTextAlign(Paint.Align.CENTER);
    textPaint.setAntiAlias(true);

    // 计算文本绘制位置:水平居中,垂直在条码下方居中(修正字体上下偏移)
    float xPos = canvas.getWidth() / 2f;
    float yPos = height + (textAreaHeight / 2f) - ((textPaint.descent() + textPaint.ascent()) / 2f);
    // 绘制条码对应的数字
    canvas.drawText(contentsToEncode, xPos, yPos, textPaint);

    return finalBitmap;
}

关键细节说明:

  • 调用方法时需要传入Context(用来做单位转换),比如你原来的调用可以改成:
    bitmap = encodeAsBitmap("00000871", BarcodeFormat.EAN_8, (int) (pageWidth / 72 * 2.54), (int) (pageHeight / 72 * 2.54), this);
    
  • 我用dp转像素和sp转像素处理文本区域高度和字体大小,避免在不同分辨率设备上显示错乱;
  • 计算yPos时考虑了字体的ascent/descent,保证文本在预留区域内垂直居中,不会出现偏上或偏下的情况。

进阶优化(可选):

如果需要完全贴合EAN-8的标准排版(左边4位、右边4位分别对应条码左右区域),可以把字符串拆分后分别绘制:

// 拆分EAN-8为左右两段
String leftText = contentsToEncode.substring(0,4);
String rightText = contentsToEncode.substring(4);
// 分别计算左右文本的水平位置
float leftXPos = canvas.getWidth() / 4f;
float rightXPos = canvas.getWidth() * 3 / 4f;
// 绘制左右两段文本
canvas.drawText(leftText, leftXPos, yPos, textPaint);
canvas.drawText(rightText, rightXPos, yPos, textPaint);

这样修改后生成的条码就会带着下方的数字啦,测试一下应该就能看到你想要的效果!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:50:08