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
相关产品推荐
相关产品推荐

