您的位置:首页 > 产品设计 > UI/UE

Google ZXing系列讲解(五)——ZXing 仿微信扫描UI

2017-03-02 11:19 330 查看

前言

本篇接续上一篇 Google ZXing系列讲解(四)——ZXing 解决竖屏扫描问题。在上篇文章中,通过zxing官方github中的issue回复,解决了zxing横竖屏都可以扫描条码/二维码问题。

仅仅有这个还是不够酷炫, 若扫描界面能像微信那样就好了, 可以的,少年!

本文目标:

- 探索
ViewfinderView
如何绘制默认UI

- 仿微信定制ZXing UI

少废话,上代码, 戳这里

默认扫描UI

查看zxing源码,自定义这块是在类 ViewfinderView 中实现。主要是在
onDraw
方法中处理。

接下来先分析ZXing默认的扫描线,然后再其基础上修改为微信的UI。

默认矩形尺寸的计算



这里暂时不考虑图中的菜单等选项。

抽象为坐标图像为:



这里以横轴演示,左上角为整个手机屏幕的原点,向右延伸为X轴, 向下延伸为Y轴。

ViewfinderView ->
onDraw
中,先会获取中间frame的尺寸。

Rect frame = cameraManager.getFramingRect();


分析代码发现,ZXing默认的扫描框存在一个范围,最小是240 x 240, 最大的是 1200 x 675, 最大的尺寸是按照 1920 x 1080的 5/8而来的。

private static final int MAX_FRAME_WIDTH = 1200; // = 5/8 * 1920
private static final int MAX_FRAME_HEIGHT = 675; // = 5/8 * 1080


获得尺寸后,就可以在画布上画出frame的尺寸大小,将周边蒙上阴影!

// Draw the exterior (i.e. outside the framing rect) darkened
paint.setColor(resultBitmap != null ? resultColor : maskColor);
canvas.drawRect(0, 0, width, frame.top, paint);
canvas.drawRect(0, frame.top, frame.left, frame.bottom + 1, paint);
canvas.drawRect(frame.right + 1, frame.top, width, frame.bottom + 1, paint);
canvas.drawRect(0, frame.bottom + 1, width, height, paint);


具体的思路按照图上四个区域而来!

默认激光线

// Draw a red "laser scanner" line through the middle to show decoding is active
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);


默认麻点

扫描过程中,会出现麻点,这个是由如下关键代码段处理!

possibleResultPoints = new ArrayList<>(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);
}
}
}


仿微信扫描UI

微信扫描UI,需要修改ViewfinderView 以及添加某些资源文件!先来看下微信扫描UI图。



仿微信扫描框,需要明确以下几个方面:

- 矩形框大小

- 矩形框四角的图形&颜色

- 扫描动画

矩形框大小

横屏时候, ZXing使用了默认的大小 675 x 1200, 而竖屏时候,ZXing使用了默认大小 240 x 240。

关键代码段如下:@CameraManager

public synchronized Rect getFramingRect() {
int width = findDesiredDimensionInRange(screenResolution.x, MIN_FRAME_WIDTH, MAX_FRAME_WIDTH);
int height = findDesiredDimensionInRange(screenResolution.y, MIN_FRAME_HEIGHT, MAX_FRAME_HEIGHT);

int leftOffset = (screenResolution.x - width) / 2;
int topOffset = (screenResolution.y - height) / 2;
... ...
}


private static int findDesiredDimensionInRange(int resolution, int hardMin, int hardMax) {
int dim = 5 * resolution / 8; // Target 5/8 of each dimension
if (dim < hardMin) {
return hardMin;
}
if (dim > hardMax) {
return hardMax;
}
return dim;
}


矩形框四角的图形&颜色

颜色很好确定,画图形的选择有几种方式

- 画8条线

- 画8个矩形

无意中发现这篇文章 一片枫叶专栏, 该作者实现了一个 android-zxingLibrary库,查看该lib中有关画边框的代码,发现使用矩形方式画了8个, 而且使用了
AttributeSet
来设计,可以在xml中设置边框的宽高等属性! 下文,会做详细说明

扫描动画

上下移动的线条,使用了图片形式。扫描动画原理很简单, onDraw方法被系统不断的调用,在其中控制到上下移动的距离,以及对距离的判断即可!

private void drawScanLight(Canvas canvas, Rect frame) {

if (scanLineTop == 0) {
scanLineTop = frame.top;
}

if (scanLineTop >= frame.bottom - 30) {
scanLineTop = frame.top;
} else {
scanLineTop += SCAN_VELOCITY;// SCAN_VELOCITY可以在属性中设置,默认为5
}
Rect scanRect = new Rect(frame.left, scanLineTop, frame.right, scanLineTop + 30);
canvas.drawBitmap(scanLight, null, scanRect, paint);
}


实现步骤

1.attrs文件

在values目录中添加attrs文件, 参考android-zxingLibrary

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="innerrect">
<attr name="inner_width" format="dimension"/>
<attr name="inner_height" format="dimension"/>
<attr name="inner_margintop" format="dimension" />
<attr name="inner_corner_color" format="color" />
<attr name="inner_corner_length" format="dimension" />
<attr name="inner_corner_width" format="dimension" />
<attr name="inner_scan_bitmap" format="reference" />
<attr name="inner_scan_speed" format="integer" />
<attr name="inner_scan_iscircle" format="boolean" />
</declare-styleable>
</resources>


本文并没有使用到所有属性,这些属性在哪里使用,答案是在 工程目录下的layout-> capture.xml

<com.google.zxing.client.android.ViewfinderView
android:id="@+id/viewfinder_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:inner_corner_length="30dp" //四角绿颜色矩形的长度
app:inner_corner_width="5dp" //四角绿颜色矩形的宽度
app:inner_scan_bitmap="@drawable/scanline" //需要添加scanline图片到drawable目录中
app:inner_scan_speed="10" // 扫描线移动距离
app:inner_scan_iscircle="true" /> //扫描过程中是否显示麻点


2.ViewfinderView修改

修改了其中很多内容, 涉及的方法包括:

- public ViewfinderView(Context context, AttributeSet attrs)

- private void initInnerRect(Context context, AttributeSet attrs)

- public void onDraw(Canvas canvas)

- private void drawFrameBounds(Canvas canvas, Rect frame)

- private void drawScanLight(Canvas canvas, Rect frame)

关键点都添加了 //add by tan 注释
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐