一、概述
相信Adnroid开发都知道,世界上有四款扫描器,Zxing 、Zbar ,Barcode4J、OkapiBarcode 前二者应用较广泛,至于介绍与区别就在此阐述,网上有很多。此文主要介绍在在使用过程中,官方客户端各种达不到需求。相信很多童鞋都有此体会,所以借此机会就在Zxing 官方客户端基础上修改,去除无用功能并二次封装达到可扩展。
- 官方客户端目前问题汇总
- 设置功能多余
- 竖屏后不能正向扫描条形码
- 扫描框大小、颜色、扫描线配置不够灵活
- 无生成二维码、主动识别二维码功能
- 介于以上问题,于是该库就华丽的诞生
- 修复竖屏不能正向扫描条形码
- 可定制扫描框与扫描线样式
- 加入创建二维码、识别图片中的二维码功能
二、效果图
三、代码说明
定义所用的变量
private int laserColor = Scanner.color.VIEWFINDER_LASER;
private int laserFrameBoundColor = laserColor;
private int laserLineTop;
private int laserLineHeight;
private int laserMoveSpeed;
private int laserFrameCornerWidth;
private int laserFrameCornerLength;
private int laserLineResId;
private String drawText = "将二维码放入框内,即可自动扫描";
private int drawTextSize;
private int drawTextColor = Color.WHITE;
private boolean drawTextGravityBottom = true;
private int drawTextMargin;
darw方法
@Override
public void onDraw(Canvas canvas) {
if (cameraManager == null) {
return;
}
Rect frame = cameraManager.getFramingRect();
Rect previewFrame = cameraManager.getFramingRectInPreview();
if (frame == null || previewFrame == null) {
return;
}
drawMask(canvas, frame);
if (resultBitmap != null) {
paint.setAlpha(CURRENT_POINT_OPACITY);
canvas.drawBitmap(resultBitmap, null, frame, paint);
} else {
drawFrame(canvas, frame);
drawFrameCorner(canvas, frame);
drawText(canvas, frame);
drawLaserLine(canvas, frame);
drawResultPoint(canvas, frame, previewFrame);
moveLaserSpeed(frame);
}
}
扫描框的4个角
/**
* 绘制扫描框4角
*
* @param canvas
* @param frame
*/
private void drawFrameCorner(Canvas canvas, Rect frame) {
paint.setColor(laserFrameBoundColor);
paint.setStyle(Paint.Style.FILL);
canvas.drawRect(frame.left - laserFrameCornerWidth, frame.top, frame.left, frame.top
+ laserFrameCornerLength, paint);
canvas.drawRect(frame.left - laserFrameCornerWidth, frame.top - laserFrameCornerWidth, frame.left
+ laserFrameCornerLength, frame.top, paint);
canvas.drawRect(frame.right, frame.top, frame.right + laserFrameCornerWidth,
frame.top + laserFrameCornerLength, paint);
canvas.drawRect(frame.right - laserFrameCornerLength, frame.top - laserFrameCornerWidth,
frame.right + laserFrameCornerWidth, frame.top, paint);
canvas.drawRect(frame.left - laserFrameCornerWidth, frame.bottom - laserFrameCornerLength,
frame.left, frame.bottom, paint);
canvas.drawRect(frame.left - laserFrameCornerWidth, frame.bottom, frame.left
+ laserFrameCornerLength, frame.bottom + laserFrameCornerWidth, paint);
canvas.drawRect(frame.right, frame.bottom - laserFrameCornerLength, frame.right
+ laserFrameCornerWidth, frame.bottom, paint);
canvas.drawRect(frame.right - laserFrameCornerLength, frame.bottom, frame.right
+ laserFrameCornerWidth, frame.bottom + laserFrameCornerWidth, paint);
}
图片画与画笔扫描线
/**
* 画扫描线
*
* @param canvas
* @param frame
*/
private void drawLaserLine(Canvas canvas, Rect frame) {
if (laserLineResId == 0) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(laserColor);
canvas.drawRect(frame.left, laserLineTop, frame.right, laserLineTop + laserLineHeight, paint);
} else {
if (laserLineBitmap == null)
laserLineBitmap = BitmapFactory.decodeResource(getResources(), laserLineResId);
int height = laserLineBitmap.getHeight();
if (isLaserGridLine) {
RectF dstRectF = new RectF(frame.left, frame.top, frame.right, laserLineTop);
Rect srcRect = new Rect(0, (int) (height - dstRectF.height()), laserLineBitmap.getWidth(), height);
canvas.drawBitmap(laserLineBitmap, srcRect, dstRectF, paint);
}
else {
if (laserLineHeight == Scanner.dp2px(getContext(), DEFAULT_LASER_LINE_HEIGHT)) {
laserLineHeight = laserLineBitmap.getHeight() / 2;
}
Rect laserRect = new Rect(frame.left, laserLineTop, frame.right, laserLineTop + laserLineHeight);
canvas.drawBitmap(laserLineBitmap, null, laserRect, paint);
}
}
}
扫描提示文字
/**
* 绘制提示文字
*
* @param canvas
* @param frame
*/
private void drawText(Canvas canvas, Rect frame) {
int width = canvas.getWidth();
paint.setColor(drawTextColor);
paint.setTextSize(drawTextSize);
final float textWidth = paint.measureText(drawText);
float x = (width - textWidth) / 2;
float y = drawTextGravityBottom ? frame.bottom + drawTextMargin : frame.top - drawTextMargin;
canvas.drawText(drawText, x, y, paint);
}
三、使用
直接在layout xml
使用ScannerView
即可
重写onResume
调用mScannerView.onResume();
@Override
protected void onResume() {
mScannerView.onResume();
super.onResume();
}
注册扫描成功监听器setOnScannerCompletionListener
/**
* 扫描成功后将调用
*
* @param rawResult 扫描结果
* @param parsedResult 结果类型
* @param barcode 扫描后的图像
*/
void OnScannerCompletion(Result rawResult, ParsedResult parsedResult, Bitmap barcode);
调用如下方法获取类型
ParsedResultType type = parsedResult.getType();
可根据type
强转为相应的对象,按项目需求处理。每个项目都有不同的需求,所以此库将最终处理结果丢给你们自己咯,想怎么玩就怎么玩,下面代码是在 sample 中
switch (type) {
case ADDRESSBOOK:
AddressBookParsedResult addressResult = (AddressBookParsedResult) parsedResult;
bundle.putStringArray(Intents.AddressBookConnect.NAME, addressResult.getNames());
bundle.putStringArray(Intents.AddressBookConnect.NUMBER, addressResult.getPhoneNumbers());
bundle.putStringArray(Intents.AddressBookConnect.EMAIL, addressResult.getEmails());
break;
case URI:
URIParsedResult uriParsedResult = (URIParsedResult) parsedResult;
bundle.putString(Intents.URIContents.URI, uriParsedResult.getURI());
break;
case TEXT:
bundle.putString(Intents.Scan.RESULT, rawResult.getText());
break;
}
生成二维码
Bitmap bitmap = QREncode.encodeQR(MainActivity.this,
new QREncode.Builder() .setColor(getResources().getColor(R.color.colorPrimary))
.setParsedResultType(ParsedResultType.URI)
.setContents("https://github.com/mylhyl")
.build());
imageView.setImageBitmap(bitmap);
四、样式设置
方法名 | 说明 | 默认值 |
---|---|---|
toggleLight | 切换闪光灯 | 关 false |
setMediaResId | 设置扫描完成播放声音 | 无 |
setLaserFrameBoundColor | 扫描框4角颜色 | 绿色 0xff00ff00 |
setLaserFrameCornerLength | 扫描框4角长度 | 15dp |
setLaserFrameCornerWidth | 扫描框4角宽度 | 2dp |
setLaserColor | 扫描线颜色 | 绿色 0xff00ff00 |
setLaserLineResId | 条形扫描线图片资源 | 无 |
setLaserGridLineResId | 网格扫描线资源 | 无 |
setLaserLineHeight | 扫描线高度 | 2dp |
setLaserFrameSize | 设置扫描框大小 | 屏幕5/8 |
setLaserFrameTopMargin | 设置扫描框与屏幕距离 | 屏幕5/8-状态 |
setDrawText | text -> 内容 textSize -> 文字大小 textColor -> 文字颜色 isBottom -> 是否在扫描框下方 textMargin -> 离扫描框间距 |
text -> 将二维码放入框内,即可自动扫描 textSize -> 16sp textColor -> 白色 isBottom -> true textMargin -> 20dp |