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

来源:互联网 发布:信访网络舆情应急预案 编辑:程序博客网 时间:2024/05/21 05:20

一、概述

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

  • 官方客户端目前问题汇总
    • 设置功能多余
    • 竖屏后不能正向扫描条形码
    • 扫描框大小、颜色、扫描线配置不够灵活
    • 无生成二维码、主动识别二维码功能
  • 介于以上问题,于是该库就华丽的诞生
    • 修复竖屏不能正向扫描条形码
    • 可定制扫描框与扫描线样式
    • 加入创建二维码、识别图片中的二维码功能

二、效果图

这里写图片描述

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

三、代码说明

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

    1. 如下图双击 makeJar
      这里写图片描述

    2. 等待控制出现 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;// 扫描线默认移动距离pxprivate 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方法

@Overridepublic 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();

@Overrideprotected 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

我也建了个Q群:435173211,一起交流交流!

这里写图片描述

4 0
原创粉丝点击