如果你下载了ZXing的源码和ZXing的core.jar包,那么你现在就可以进行如下的一系列修改来自定义你的二维码扫描了。
本文链接:http://blog.csdn.net/lemon_tree12138/article/details/47088951 -- Coding-Naga
--转载请注明出处
这一步其实是相对来说还是比较复杂的。因为这里需要针对两个不同方面进行修改,一个是横竖屏的切换,另一个是图像伸缩的修改。
(1)修改Manifest中CaptureActivity类的属性为android:screenOrientation="sensor"
(2)修改CaptureActivity类,在onResume方法中调用下面的代码:
private void setOrientation() { WindowManager manager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); mRotation = manager.getDefaultDisplay().getRotation(); boolean orientationFlag = true; int screenState = CaptureActivity.this.getResources().getConfiguration().orientation; if (screenState == Configuration.ORIENTATION_LANDSCAPE){ orientationFlag = false; mOrientationFlag = false; } else if (screenState ==Configuration.ORIENTATION_PORTRAIT) { orientationFlag = true; mOrientationFlag = true; } EventBus.getDefault().post(orientationFlag, RESET_ORIENTATION); }
(3)修改DecodeHandler类
在如下代码
<span style="font-family:Courier New;font-size:14px;">PlanarYUVLuminanceSource source = activity.getCameraManager().buildLuminanceSource(data, width, height);</span>
的上方添加以下代码:
if (mPortraitFlag) { 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; // Here we are swapping, that's the difference to #11 width = height; height = tmp; data = rotatedData; }mPortraitFlag的获得是通过Android的总线事件来获得:
@Subscriber(tag = "reset_orientation") private void updateFlag(boolean flag) { mPortraitFlag = flag; }(4)在CameraConfigurationManager类的initFromCameraParameters方法中
Point screenResolutionForCamera = new Point();代码的下面添加如下代码:
if (CaptureActivity.getOrientationFlag()) { screenResolutionForCamera.x = screenResolution.x; screenResolutionForCamera.y = screenResolution.y; if (screenResolution.x < screenResolution.y) { screenResolutionForCamera.x = screenResolution.y; screenResolutionForCamera.y = screenResolution.x; } cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolutionForCamera); } else { cameraResolution = CameraConfigurationUtils.findBestPreviewSizeValue(parameters, screenResolution); }
(5)在CameraConfigurationManager类的setDesiredCameraParameters方法中
camera.setParameters(parameters);代码的上面添加如下代码:
String model = android.os.Build.MODEL; int extraAngle = 0; if (model.equalsIgnoreCase("MediaPad 10 FHD")) { extraAngle = -90; } else if (model.startsWith("EBEN")) { extraAngle = -90; } switch (CaptureActivity.getRotationFlag()) { case Surface.ROTATION_0: camera.setDisplayOrientation((360 + 90 + extraAngle) % 360); break; case Surface.ROTATION_90: camera.setDisplayOrientation((360 + 0 + extraAngle) % 360); break; case Surface.ROTATION_180: camera.setDisplayOrientation((360 + 270 + extraAngle) % 360); break; case Surface.ROTATION_270: camera.setDisplayOrientation((360 + 180 + extraAngle) % 360); break; default: break; }这里是对部分机型进行了一个简单的适配。
(6)在CameraManager类的getFramingRectInPreview方法中作如下修改:
if (mPortraitFlag) { 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; } else { 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; }
我们通过CameraManager类中的findDesiredDimensionInRange方法来修改扫描矩形的大小和边长比例。
int dim = 5 * resolution / 8;
上面代码中5和8就是用来修改这个矩形大小的值,你可以尝试着来实践一下。
第1步:
在com.google.zxing.client.android.CaptureActivity类中,将
characterSet = intent.getStringExtra(Intents.Scan.CHARACTER_SET);
这一句修改为:
characterSet = "ISO-8859-1";
第2步:
在handleDecodeInternally方法中,修改如下代码:
CharSequence displayContents = resultHandler.getDisplayContents(); String decodeContent = ""; try { decodeContent = new String(displayContents.toString().getBytes(characterSet), "UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); }以上两步就是把编码格式转换为了UTF-8格式了。
针对com.google.zxing.client.android包下ViewfinderView类
/** * 绘制扫描框上的四个边角 * @param canvas * @param frame */ private void drawFourCorner(Canvas canvas, Rect frame) { paint.setColor(getResources().getColor(R.color.green)); // 左上角 canvas.drawRect(frame.left, frame.top, frame.left + 30, frame.top + 10, paint); canvas.drawRect(frame.left, frame.top, frame.left + 10, frame.top + 30, paint); // 右上角 canvas.drawRect(frame.right - 30, frame.top, frame.right, frame.top + 10, paint); canvas.drawRect(frame.right - 10, frame.top, frame.right, frame.top + 30, paint); // 左下角 canvas.drawRect(frame.left, frame.bottom - 10, frame.left + 30, frame.bottom, paint); canvas.drawRect(frame.left, frame.bottom - 30, frame.left + 10, frame.bottom, paint); // 右下角 canvas.drawRect(frame.right - 30, frame.bottom - 10, frame.right,frame.bottom, paint); canvas.drawRect(frame.right - 10, frame.bottom - 30, frame.right,frame.bottom, paint); }
效果:
这里我们通过三种方式来显示扫描线条:
(1)原生的红色线条
(2)自定义的一个会移动的线条
(3)自定义一张会移动的图片
实现代码如下:
(1)原生的红色线条
这里没有做什么特别地修改,只是对绘制线条的这一模块进行了一个适当地封装,为了更好地让“用户”去选择应该使用哪一个线条更合适。
/** * 原生的扫描线条 * * @param canvas * @param frame */ private void drawSlidingRawLine(Canvas canvas, Rect frame) { Rect previewFrame = cameraManager.getFramingRectInPreview(); paint.setColor(laserColor); paint.setAlpha(SCANNER_ALPHA[scannerAlpha]); scannerAlpha = (scannerAlpha + 1) % SCANNER_ALPHA.length; int middle = frame.height() / 2 + frame.top; canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint); float scaleX = frame.width() / (float) previewFrame.width(); float scaleY = frame.height() / (float) previewFrame.height(); List<ResultPoint> currentPossible = possibleResultPoints; List<ResultPoint> currentLast = lastPossibleResultPoints; int frameLeft = frame.left; int frameTop = frame.top; if (currentPossible.isEmpty()) { lastPossibleResultPoints = null; } else { possibleResultPoints = new ArrayList<ResultPoint>(5); lastPossibleResultPoints = currentPossible; paint.setAlpha(CURRENT_POINT_OPACITY); paint.setColor(resultPointColor); synchronized (currentPossible) { for (ResultPoint point : currentPossible) { canvas.drawCircle( frameLeft + (int) (point.getX() * scaleX), frameTop + (int) (point.getY() * scaleY), POINT_SIZE, paint); } } } if (currentLast != null) { paint.setAlpha(CURRENT_POINT_OPACITY / 2); paint.setColor(resultPointColor); synchronized (currentLast) { float radius = POINT_SIZE / 2.0f; for (ResultPoint point : currentLast) { canvas.drawCircle( frameLeft + (int) (point.getX() * scaleX), frameTop + (int) (point.getY() * scaleY), radius, paint); } } } }(2)自定义的一个会移动的线条
/** * 以下为用渐变线条作为扫描线 * * @param canvas * @param frame */ private void drawSlidingSolidLine(Canvas canvas, Rect frame) { // 渐变图为矩形 mDrawable.setShape(GradientDrawable.RECTANGLE); // 渐变图为线型 mDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); // 线型矩形的四个圆角半径 mDrawable.setCornerRadii(new float[] { 8, 8, 8, 8, 8, 8, 8, 8 }); // 位置边界 mRect.set(frame.left + 10, frame.top + i, frame.right - 10, frame.top + 3 + i); // 设置渐变图填充边界 mDrawable.setBounds(mRect); // 画出渐变线条 mDrawable.draw(canvas); }(3)自定义一张会移动的图片
/** * 以下为图片作为扫描线 * * @param canvas * @param frame */ private void drawSlidingImage(Canvas canvas, Rect frame) { mRect.set(frame.left - 6, frame.top + i - 6, frame.right + 6, frame.top + 6 + i); lineDrawable.setBounds(mRect); lineDrawable.draw(canvas); }