您的位置:首页 > 移动开发 > Android开发

Android Zxing 扫描器 扫描框、扫描线定制样式

2016-07-08 10:59 459 查看

一、概述

相信Adnroid开发都知道,世界上有四款扫描器,ZxingZbarBarcode4JOkapiBarcode 前二者应用较广泛,至于介绍与区别就在此阐述,网上有很多。此文主要介绍在在使用过程中,官方客户端各种达不到需求。相信很多童鞋都有此体会,所以借此机会就在Zxing 官方客户端基础上修改,去除无用功能并二次封装达到可扩展。

官方客户端目前问题汇总

设置功能多余

竖屏后不能正向扫描条形码

扫描框大小、颜色、扫描线配置不够灵活

无生成二维码、主动识别二维码功能

介于以上问题,于是该库就华丽的诞生

修复竖屏不能正向扫描条形码

可定制扫描框与扫描线样式

加入创建二维码、识别图片中的二维码功能

二、效果图



本库地址:https://github.com/mylhyl/Android-Zxing

三、代码说明

Zxing 核心代码 https://github.com/zxing/zxing/tree/master/core 不作任何修改也不需要修改,只管用就行主要修改客户端代码。你可以自己编译成 jar 或者直接下源码拷到工程,可以参考Zxing编译。也可以到github下载本库,利用gradle编译

如下图双击 makeJar



等待控制出现 BUILD SUCCESSFUL 即编译完成,zxing 工程目录build将出libs目录



精简后的代码,去掉资源文件、扫描历史记录、分享等,目录结构如下



camera 摄像头相关

common 全局静态常量相关

decode 解析二维码相关

encode 生成二维码相关

OnScannerCompletionListener 扫描成功接口

ViewfinderView 扫描预览视图

ScannerView 新增自定义View,包括 ViewfinderView 、SurfaceView,公开一些样式设置方法,具体使用后面介绍

样式定义上来说,其实就在darw方法中,与平时自定义View一样,废话不多说来看一下干货

定义所用的变量

private int laserColor = Scanner.color.VIEWFINDER_LASER;//扫描线颜色
private int laserFrameBoundColor = laserColor;//扫描框4角颜色
private int laserLineTop;// 扫描线最顶端位置
private int laserLineHeight;//扫描线默认高度
private int laserMoveSpeed;// 扫描线默认移动距离px
private int laserFrameCornerWidth;//扫描框4角宽
private int laserFrameCornerLength;//扫描框4角高
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;
}
// 绘制扫描框以外4个区域
drawMask(canvas, frame);
// 如果有二维码结果的Bitmap,在扫取景框内绘制不透明的result Bitmap
if (resultBitmap != null) {
paint.setAlpha(CURRENT_POINT_OPACITY);
canvas.drawBitmap(resultBitmap, null, frame, paint);
} else {
drawFrame(canvas, frame);//绘制扫描框
drawFrameCorner(canvas, frame);//绘制扫描框4角
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)//图片资源文件转为 Bitmap
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;//文字开始位置
//根据 drawTextGravityBottom 文字在扫描框上方还是下文,默认下方
float y = drawTextGravityBottom ? frame.bottom + drawTextMargin : frame.top - drawTextMargin;
canvas.drawText(drawText, x, y, paint);
}


三、使用

直接在
layout xml
使用
ScannerView
即可

<com.mylhyl.zxing.scanner.ScannerView
android:id="@+id/scanner_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />


重写
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-状态
setDrawTexttext -> 内容
textSize -> 文字大小
textColor -> 文字颜色
isBottom -> 是否在扫描框下方
textMargin -> 离扫描框间距
text -> 将二维码放入框内,即可自动扫描
textSize -> 16sp
textColor -> 白色
isBottom -> true
textMargin -> 20dp

点击加入群



我建了个微信公众号,我们将每天为您推送优质文章、开源库及学习心得,欢迎关注。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  zxing 扫描线