Android ZXing 踩坑

由于项目中要用到二维码扫描功能,在上学的时候便听老师说过ZXing,第一反应就是找ZXing。经过网上的查找发现ZXing是谷歌开源的,果然还是比较主流的。于是便下载了一个包。其中android才是我关心的内容。导入了官方包运行了起来。真是很酷炫啊。。。为嘛是横屏!!!于是开始踩坑。

前面的顺利

我下载了官方最新的3.2.1的版本,首先我再网上搜索如何改为竖屏(网上搜索相关内容这一步很简单)。改好之后发现似乎挺简单的。难道就这样容易就搞定了吗?当时用了2个1920*1080分辨率,发现没问题。

开始踩坑

当我换了一个480*8001280*720分辨率手机的时候出现问题了。果然也不是那样简单和无脑的 – -!

相框拉伸

查看了源码,其中相框的绘制是在ViewfinderView中的onDraw()中实现的,onDraw中第一个方法就是

Rect frame = cameraManager.getFramingRect();通过这句话便知道了是通过CameraManager
getFramingRect方法获取大小的。我们进入到CameraManager中重写改写为这样

//int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
//int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);
DisplayMetrics metrics = context.getResources().getDisplayMetrics();
int  width = (int)  (metrics.widthPixels * 0.6);
int  height = width;

其中注释的部分为原来的实现。我讲高度和宽度都改为屏幕宽度的0.6倍。这时候,已经是正常的正方形了。

图像变形

网上的解决方案在CameraConfigurationManager中的initFromCameraParameters方法中在
Log.i(TAG, "Screen resolution in current orientation: " + screenResolution);后增加如下方法。

Point screenResolutionForCamera = new Point();
    screenResolutionForCamera.x = screenResolution.x;
    screenResolutionForCamera.y = screenResolution.y;
    // preview size is always something like 480*320, other 320*480
    if (screenResolution.x < screenResolution.y) {
      screenResolutionForCamera.x = screenResolution.y;
      screenResolutionForCamera.y = screenResolution.x;
}

并将
cameraResolution=CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
更改为
cameraResolution=CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolutionForCamera);
这时候我运行居然还是拉升状态。查看了以前的源码发现和现在的有点不同,网上的基本都是说的2.x的。
在3.2.1中把
bestPreviewSize=CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution);
改为
bestPreviewSize=CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolutionForCamera);
再次运行程序发现图像不会拉升了。

扫描不能识别

正当我以为一切都结束的时候。我发现扫描几乎不能识别。后面查阅后发现原来是改为竖屏的原因。

1.更改CameraManagergetFramingRectInPreview方法里面的代码

//         rect.left = rect.left * cameraResolution.x / screenResolution.x;
//         rect.right = rect.right * cameraResolution.x / screenResolution.x;
//         rect.top = rect.top * cameraResolution.y / screenResolution.y;
//         rect.bottom = rect.bottom * cameraResolution.y / screenResolution.y;
            rect.left = rect.left * cameraResolution.y / screenResolution.x;
            rect.right = rect.right * cameraResolution.y / screenResolution.x;
            rect.top = rect.top * cameraResolution.x / screenResolution.y;
            rect.bottom = rect.bottom * cameraResolution.x / screenResolution.y;

注释部分为原来的代码,后面为更改后的代码。

2.在DecodeHandlerdecode(byte[] data, int width, int height)方法PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);前增加如下代码

byte[] rotatedData =new byte[data.length];
        for(int y =0; y < height; y++) {
            for(int x =0; x < width; x++)
                rotatedData[x * height + height - y -1] = data[x + y * width];
        }
int tmp = width;
width = height;
height = tmp;
data = rotatedData;

到这里前面遇见的问题也就搞定了。
其中如果只改第一步不改第二部会报错
只有第二步没有第一步会无法识别二维码

自定义样式

只需要在ViewfinderView中的onDraw方法里面去绘制就可以了。方法也很简单就不介绍了。别忘记做适配,可以改为自定义属性用xml配置,通过dimens来适配不同分辨率。

最终效果

《Android ZXing 踩坑》 1.png

    原文作者:TSimeon
    原文地址: https://www.jianshu.com/p/c8c3004e5d9d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞