由于项目中要用到二维码扫描功能,在上学的时候便听老师说过ZXing
,第一反应就是找ZXing
。经过网上的查找发现ZXing
是谷歌开源的,果然还是比较主流的。于是便下载了一个包。其中android
才是我关心的内容。导入了官方包运行了起来。真是很酷炫啊。。。为嘛是横屏!!!于是开始踩坑。
前面的顺利
我下载了官方最新的3.2.1的版本,首先我再网上搜索如何改为竖屏(网上搜索相关内容这一步很简单)。改好之后发现似乎挺简单的。难道就这样容易就搞定了吗?当时用了2个1920*1080
分辨率,发现没问题。
开始踩坑
当我换了一个480*800
和1280*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.更改CameraManager
中getFramingRectInPreview
方法里面的代码
// 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.在DecodeHandler
中decode(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
来适配不同分辨率。
最终效果
1.png