ZXing自定义扫码界面(超简单)
!!!注意!!!2020.6.20
现在不推荐本文章提到的库barcodescanner
,推荐另一个库
https://github.com/bingoogolapple/BGAQRCode-Android
!!!注意!!!
这里使用到的库(很难自定义扫码框样式等内容)
https://github.com/dm77/barcodescanner
barcodescanner是基于ZXing进行了二次开发,简化了ZXing的集成和二次定制难度,方便快速集成和开发,并且扫描性能和结果比较稳定
1.引入
repositories {
jcenter()
}
implementation 'me.dm7.barcodescanner:zxing:1.9.13'
如果你的项目中已经有了ZXing库,会导致重复引入产生冲突,所以需要使用到exclude方式重复引入
compile ('me.dm7.barcodescanner:zxing:1.9.8'){//compile 可以替换为implementation
exclude group:"com.google.zxing"
}
当然,相机权限什么的不要忘了:
< users-permission android :name = “ android.permission.CAMERA ” />
2.界面布局
这里我们是实现的自定义扫码界面,所以在你首先要进行扫码的activity布局:
这里超简单,就是一个FrameLayout
和TextView
布局xml文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="swust.yuqiaodan.tomatoapp.mvp.ui.activity.ScanQRActivity">
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<TextView
android:id="@+id/cancel_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:gravity="center"
android:textSize="25sp"
android:textColor="#000000"
android:layout_marginBottom="100dp"
/>
</RelativeLayout>
3.扫码代码
注释写的很清楚,不再赘述
注意实现接口:ZXingScannerView.ResultHandler
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.FrameLayout;
import android.widget.TextView;
import com.google.zxing.Result;
import java.util.ArrayList;
import me.dm7.barcodescanner.zxing.ZXingScannerView;
import swust.yuqiaodan.tomatoapp.R;
public class ScanQRActivity extends AppCompatActivity implements ZXingScannerView.ResultHandler{
FrameLayout content_frame;//放置ZXingScannerView
TextView cancel_scan;//展示扫码得到的结果
ArrayList<String> resultList;//存放多次扫描的结果
ZXingScannerView zBarScannerView;//框架内部的扫码view
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scan_qr);
//初始化一些界面组件
resultList=new ArrayList<>();
content_frame=findViewById(R.id.content_frame);
cancel_scan=findViewById(R.id.cancel_scan);
//初始化扫码view
zBarScannerView=new ZXingScannerView(this);
//添加zBarScannerView到FrameLayout
content_frame.addView(zBarScannerView);
//添加扫码结果回调
zBarScannerView.setResultHandler(this);
//自动对焦
zBarScannerView.setAutoFocus(true);
//启动相机
zBarScannerView.startCamera();
}
@Override
public void handleResult(Result result) {
/**
* result就是扫码的结果
* result.getText()可以获取到扫码得到的str
* 这里可以按业务需求做正则判断
* 这里可以做扫码完成后需要做的其他操作
* 比如发出网络请求,展示结果等等
*
* */
resultList.add(result.getText());//暂存扫码结果
cancel_scan.setText(result.getText()+"("+resultList.size()+")");//展示结果
scanAgain();//重新开始下一次扫码
}
public void scanAgain(){//重新开始下一次扫码
zBarScannerView.resumeCameraPreview(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
zBarScannerView.stopCamera();//关闭相机
}
}
4.补充点
以上就是自定义扫码的基本实现了,出于业务上的需求,我们需要做一些补充
4.1 scanAgain()
优化
原本我们在得到扫码结果后立刻就开始下一次扫码,这里其实很快的,会导致设备还没有来得及移开就又开始扫码了,所以可以人为的设置下次开启扫码时间,比如我这里设置的800微秒
JAVA
public void scanAgain() {
Observable.just(null)//间息0.8重新开始扫描
.delay(800, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(Object o) {
startScanAgain();
}
}
);
}
Kotlin
private fun scanAgain() {
Observable.just(null)
.delay(800, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
zBarScannerView!!.resumeCameraPreview(this@ScanQRActivity)
})
}
4.2 定制扫码模式 防止误扫和错误识别
zxing为我们提供了这么多编码格式的条形码和二维码
package com.google.zxing;
public enum BarcodeFormat {
AZTEC,
CODABAR,
CODE_39,//条形码编码格式
CODE_93,//条形码编码格式
CODE_128,//条形码编码格式
DATA_MATRIX,
EAN_8,
EAN_13,
ITF,
MAXICODE,
PDF_417,
QR_CODE,//二维码
RSS_14,
RSS_EXPANDED,
UPC_A,//条形码编码格式
UPC_E,//条形码编码格式
UPC_EAN_EXTENSION;
private BarcodeFormat() {
}
}
然而其实我们一般在业务上不可能都需要去扫描这些编码格式的码,而由于有些时候相机对焦不及时,模糊或者误扫描错误的码都会导致不必要的错误
我们可以指定我们业务上的需要扫描哪些码,来避开以上错误,比如最常常使用到的条形码的CODE-128编码格式,和二维码QR_CODE。我就指定只扫描这两种码,做法如下
import static com.google.zxing.BarcodeFormat.CODE_128;
import static com.google.zxing.BarcodeFormat.QR_CODE;
public class ScanReceiptsActivity extends BaseActivity implements ZXingScannerView.ResultHandler {
......
//扫码模式
List<BarcodeFormat> formats;
onCreate(Bundle savedInstanceState){
......
formats=new ArrayList<>();
formats.add(CODE_128);
formats.add(QR_CODE);
zBarScannerView = new ZXingScannerView(this);
zBarScannerView.setFormats(formats);
}
}
保持更新
备注1 scanAgain重启相机可以采用以下方式进行延迟一点点 这里是延迟了0.8秒
//java
@SuppressLint("CheckResult")
public void scanAgain(){
Observable.just(1)
.delay(800, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
new Consumer<Object>() {
@Override
public void accept(Object o) throws Exception {
zBarScannerView.resumeCameraPreview(ScanActivity.this);
}
}
);
}
//kotlin
private fun scanAgain() {
Observable.just(null)
.delay(800, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
zBarScannerView!!.resumeCameraPreview(this@NewBindExpressActivity)
})
}
备注2 扫码时返回桌面再返回 如何重启相机
在onPause()中手动关闭相机
在onResume()再启动即可
@Override
protected void onResume() {
super.onResume();
//启动相机
zBarScannerView.startCamera();
}
@Override
protected void onPause() {
super.onPause();
zBarScannerView.stopCamera();
}