您的位置:首页 > 移动开发 > Android开发

Android 中二维码扫码功能集成zxing注意事项 自定义扫码取景区

2017-03-09 12:45 1781 查看
Android二维码扫码集成:https://github.com/zxing/zxing

1.下载下来之后解压,在你的项目中file → new → import module 将该文件夹导入项目,并将app依赖于这个module(如下图),下面开始使用【开发工具:Android
studio】



2.扫码功能:你可以定义个按钮,点击按钮时调用下面的方法(checkCameraPermission())

//检查是否开启了相机权限【Android 6.0之后必须添加】

private void checkCameraPermission() {

if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {

//如果没有授权,则请求授权

ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_CALL_CAMERA);

} else {

//有授权,直接开启摄像头扫描

callCapture("UTF-8");//打开扫码签到

}

}

private void callCapture(String characterSet) {

/**

* 获取屏幕的宽度,并将宽度的2/3作为扫码区宽度

*/

int width = Tools.getScreenW(getContext()) * 2 / 3;

Intent intent = new Intent();

intent.setAction(Intents.Scan.ACTION);

// intent.putExtra(Intents.Scan.MODE, Intents.Scan.QR_CODE_MODE);

intent.putExtra(Intents.Scan.CHARACTER_SET, characterSet);

/**

* WIDTH==HEIGHT 设置方形扫码取景区

* 取景区的总宽度是屏幕宽度的2/3——适配所有机型

* */

intent.putExtra(Intents.Scan.WIDTH, width);

intent.putExtra(Intents.Scan.HEIGHT, width);//

// intent.putExtra(Intents.Scan.PROMPT_MESSAGE, "type your prompt message");

intent.setClass(getContext(), CaptureActivity.class);//进入zxing模块中的CaptureActivity

startActivityForResult(intent, REQUEST_CODE);

}

@Override

public void onActivityResult(int requestCode, int resultCode, Intent data) {

//获取扫描结果

if (null != data && requestCode == REQUEST_CODE) {

switch (resultCode) {

case Activity.RESULT_OK:

LogD.d("扫描返回RESULT:\n" + data.getStringExtra(Intents.Scan.RESULT));

LogD.d("扫描返回RESULT_FORMAT:\n" + data.getStringExtra(Intents.Scan.RESULT_FORMAT));

LogD.d("扫描返回URI:\n" + data.toUri(data.getFlags()));

getResult(data.getStringExtra(Intents.Scan.RESULT));//获取扫码结果

break;

default:

break;

}

}

}

【如果你不需要设置取景区域的话,上面的代码,已够用。】

3.设置取景区样式【主要调整zxing模块中的CaptureActivity,CameraManager,ViewfinderView】

第一步:调整扫码界面的样式——扫码界面的顶部添加返回按钮和标题

布局代码如下:

CaptureActivity布局代码

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent">

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

<SurfaceView

android:id="@+id/preview_view"

android:layout_width="match_parent"

android:layout_height="match_parent" />

<com.google.zxing.client.android.ViewfinderView

android:id="@+id/viewfinder_view"

android:layout_width="match_parent"

android:layout_height="match_parent" />

<include layout="@layout/layout_capture_header"

android:layout_width="match_parent"

android:layout_height="wrap_content"/>

</RelativeLayout>

</FrameLayout>

layout_capture_header.xml代码:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:padding="5dp"

android:background="@color/viewfinder_mask"

>

<ImageButton

android:id="@+id/button_back"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:background="@drawable/back" />

<TextView

android:id="@+id/textview_title"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_centerInParent="true"

android:gravity="center_vertical"

android:text="二维码扫描"

android:textColor="@android:color/white"

android:textSize="18sp" />

</RelativeLayout>

第二步:添加返回事件(在CaptureActivity的onResume方法中添加以下代码段)【完成了扫码界面的调整】



第三步:调整扫码取景区的相对位置【上面已经传了相对宽度和高度进入CaptureActivity,取景区已经按照这个设置去设置了】【在CameraManager中调整如下——实现扫码取景区位置在偏上】



第四步:调整取景区的四个角,扫码线,取景区下发的提示文字【用以下代码段区替换ViewfinderView】(注释已经很清楚的说明了具体用法,有兴趣的自己去研究哈)

public final class ViewfinderView extends View {

private static final String TAG = "log";

/**

* 刷新界面的时间

*/

private static final long ANIMATION_DELAY = 10L;

private static final int OPAQUE = 0xFF;

/**

* 四个绿色边角对应的长度

*/

private int ScreenRate;

/**

* 四个绿色边角对应的宽度

*/

private static final int CORNER_WIDTH = 5;

/**

* 扫描框中的中间线的宽度

*/

private static final int MIDDLE_LINE_WIDTH = 4;

/**

* 扫描框中的中间线的与扫描框左右的间隙

*/

private static final int MIDDLE_LINE_PADDING = 6;

/**

* 中间那条线每次刷新移动的距离

*/

private static final int SPEEN_DISTANCE = 5;

/**

* 手机的屏幕密度

*/

private static float density;

/**

* 字体大小

*/

private static final int TEXT_SIZE = 16;

/**

* 字体距离扫描框下面的距离

*/

private static final int TEXT_PADDING_TOP = 60;

/**

* 画笔对象的引用

*/

private Paint paint;

/**

* 中间滑动线的最顶端位置

*/

private int slideTop;

/**

* 中间滑动线的最底端位置

*/

private int slideBottom;

private Bitmap resultBitmap;

private final int maskColor;

private final int resultColor;

private final int resultPointColor;

private Collection<ResultPoint> possibleResultPoints;

private Collection<ResultPoint> lastPossibleResultPoints;

private CameraManager cameraManager;

private boolean isFirst;

public ViewfinderView(Context context, AttributeSet attrs) {

super(context, attrs);

density = context.getResources().getDisplayMetrics().density;

//将像素转换成dp

ScreenRate = (int) (10 * density);

paint = new Paint();

Resources resources = getResources();

maskColor = resources.getColor(R.color.viewfinder_mask);

resultColor = resources.getColor(R.color.result_view);

resultPointColor = resources.getColor(R.color.possible_result_points);

possibleResultPoints = new HashSet<ResultPoint>(5);

}

public void setCameraManager(CameraManager cameraManager) {

this.cameraManager = cameraManager;

}

@Override

public void onDraw(Canvas canvas) {

if (cameraManager == null) return;

//中间的扫描框,你要修改扫描框的大小,去CameraManager里面修改

Rect frame = cameraManager.getFramingRect();

if (frame == null) {

return;

}

//初始化中间线滑动的最上边和最下边

if (!isFirst) {

isFirst = true;

slideTop = frame.top;

slideBottom = frame.bottom;

}

//获取屏幕的宽和高

int width = canvas.getWidth();

int height = canvas.getHeight();

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);

if (resultBitmap != null) {

// Draw the opaque result bitmap over the scanning rectangle

paint.setAlpha(OPAQUE);

canvas.drawBitmap(resultBitmap, frame.left, frame.top, paint);

} else {

//画扫描框边上的角,总共8个部分

paint.setColor(Color.GREEN);

canvas.drawRect(frame.left, frame.top, frame.left + ScreenRate,

frame.top + CORNER_WIDTH, paint);

canvas.drawRect(frame.left, frame.top, frame.left + CORNER_WIDTH, frame.top

+ ScreenRate, paint);

canvas.drawRect(frame.right - ScreenRate, frame.top, frame.right,

frame.top + CORNER_WIDTH, paint);

canvas.drawRect(frame.right - CORNER_WIDTH, frame.top, frame.right, frame.top

+ ScreenRate, paint);

canvas.drawRect(frame.left, frame.bottom - CORNER_WIDTH, frame.left

+ ScreenRate, frame.bottom, paint);

canvas.drawRect(frame.left, frame.bottom - ScreenRate,

frame.left + CORNER_WIDTH, frame.bottom, paint);

canvas.drawRect(frame.right - ScreenRate, frame.bottom - CORNER_WIDTH,

frame.right, frame.bottom, paint);

canvas.drawRect(frame.right - CORNER_WIDTH, frame.bottom - ScreenRate,

frame.right, frame.bottom, paint);

//绘制中间的线,每次刷新界面,中间的线往下移动SPEEN_DISTANCE

slideTop += SPEEN_DISTANCE;

if (slideTop >= frame.bottom) {

slideTop = frame.top;

}

// canvas.drawRect(frame.left + MIDDLE_LINE_PADDING, slideTop - MIDDLE_LINE_WIDTH / 2,

// frame.right - MIDDLE_LINE_PADDING, slideTop + MIDDLE_LINE_WIDTH / 2, paint);

Rect lineRect = new Rect();

lineRect.left = frame.left;

lineRect.right = frame.right;

lineRect.top = slideTop;

lineRect.bottom = slideTop + 18;

canvas.drawBitmap(((BitmapDrawable) (getResources().getDrawable(R.drawable.qrcode_scan_line))).getBitmap(), null, lineRect, paint);

//画扫描框下面的字()

paint.setColor(Color.WHITE);

paint.setTextSize(TEXT_SIZE * density);

paint.setAlpha(0x40);

paint.setTypeface(Typeface.DEFAULT_BOLD);

String text = getResources().getString(R.string.scan_text);

float textWidth = paint.measureText(text);

canvas.drawText(text, (width - textWidth) / 2, (float) (frame.bottom + (float) TEXT_PADDING_TOP * density), paint);

Collection<ResultPoint> currentPossible = possibleResultPoints;

Collection<ResultPoint> currentLast = lastPossibleResultPoints;

if (currentPossible.isEmpty()) {

lastPossibleResultPoints = null;

} else {

possibleResultPoints = new HashSet<ResultPoint>(5);

lastPossibleResultPoints = currentPossible;

paint.setAlpha(OPAQUE);

paint.setColor(resultPointColor);

for (ResultPoint point : currentPossible) {

canvas.drawCircle(frame.left + point.getX(), frame.top

+ point.getY(), 6.0f, paint);

}

}

if (currentLast != null) {

paint.setAlpha(OPAQUE / 2);

paint.setColor(resultPointColor);

for (ResultPoint point : currentLast) {

canvas.drawCircle(frame.left + point.getX(), frame.top

+ point.getY(), 3.0f, paint);

}

}

//只刷新扫描框的内容,其他地方不刷新

postInvalidateDelayed(ANIMATION_DELAY, frame.left, frame.top,

frame.right, frame.bottom);

}

}

public void drawViewfinder() {

resultBitmap = null;

invalidate();

}

/**

* Draw a bitmap with the result points highlighted instead of the live

* scanning display.

*

* @param barcode An image of the decoded barcode.

*/

public void drawResultBitmap(Bitmap barcode) {

resultBitmap = barcode;

invalidate();

}

public void addPossibleResultPoint(ResultPoint point) {

possibleResultPoints.add(point);

}

}

效果图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: