Android基于zxing-android-embedded实现自定义扫码界面,连续扫码
一、相关设置
1、下载zxing-android-embedded
https://github.com/journeyapps/zxing-android-embedded
2、导入到项目中,我是作为模块导入的:file->new->import module,之前直接添加依赖导入无法编辑包里的源代码(比较low)
3、添加依赖:
在项目的build.gradle文件中的dependencies添加
implementation project(':zxing-android-embedded')
二、直接调用这个库
很简单,在你的活动中添加下列代码:
new IntentIntegrator(MainActivity.this)
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)// 扫码的类型,可选:一维码,二维码,一/二维码
.setPrompt("请对准二维码")// 设置提示语
.setCameraId(0)// 选择摄像头,可使用前置或者后置
.setBeepEnabled(true)// 是否开启声音,扫完码之后会"哔"的一声
.setBarcodeImageEnabled(true)// 扫完码之后生成二维码的图片
.initiateScan();// 初始化扫码
默认的扫码活动是横屏,很多时候我们需要自定义扫码界面才能满足需求
默认扫码界面:(测试手机丢在车里了,不想下去拿了,勉强看一下)
三、自定义扫码界面:
默认的扫码界面的activity是CaptureActivity
我们需要自己写一个Activity,我写了个MyCaptureActivity,别忘了注册一下
package com.geek66.myzxing;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.journeyapps.barcodescanner.CaptureManager;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import java.util.ArrayList;
/**
* @package com.geek66.myzxing
* @name MyCaptureActivity
* @date 2019/4/29 20:58
* @auther Bibi
* @decribe TODO 扫码活动,用来替代系统默认的CaptureActivity
**/
public class MyCaptureActivity extends AppCompatActivity {
private CaptureManager captureManager;
private DecoratedBarcodeView barcodeView;
private Button btn_result;
private ArrayList<String> result_list;//存放连续扫描的结果
private int i;//计数器,记录重复扫描次数
private String[] goodsIdList;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mycapture);
barcodeView = findViewById(R.id.dbv_my);
btn_result = findViewById(R.id.btn_result);
result_list = new ArrayList<>();
captureManager = new CaptureManager(this,barcodeView);
captureManager.initializeFromIntent(getIntent(),savedInstanceState);
captureManager.setmResultCallBack(new CaptureManager.ResultCallBack() {
@Override
public void callBack(int requestCode, int resultCode, Intent intent) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode,resultCode,intent);
if(result != null&& result.getContents()!=null){
i++;
btn_result.setText("已扫描"+i+"点击查看详情");
captureManager.onResume();//重新加载扫码界面
captureManager.decode();//调用扫码方法
}
}
});
captureManager.decode();
btn_result.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if(btn_result.getText().equals("点击查看扫描结果")){
Toast.makeText(MyCaptureActivity.this, "还未进行扫码操作", Toast.LENGTH_SHORT).show();
} else {
captureManager.onPause();
Toast.makeText(MyCaptureActivity.this, "已扫码"+i , Toast.LENGTH_SHORT).show();
showListDialog(list2string(result_list));
}
}
});
}
//已扫码物品详情列表
private void showListDialog(String[] goodsIdList) {
final AlertDialog.Builder listDialog = new AlertDialog.Builder(MyCaptureActivity.this);
listDialog.setTitle("已扫码列表");
listDialog.setItems(goodsIdList, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//扩展,增加删除条目功能
}
});
listDialog.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//确认按钮事件
Toast.makeText(MyCaptureActivity.this, "确认成功", Toast.LENGTH_SHORT).show();
captureManager.closeAndFinish();//退出扫码活动
}
});
listDialog.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
listDialog.show();
}
//list转数组
public String[] list2string (ArrayList<String> list){
goodsIdList = new String[list.size()];
for(int i=0;i<list.size();i++){
goodsIdList[i] = list.get(i);
}
return goodsIdList;
}
@Override
protected void onResume() {
super.onResume();
captureManager.onResume();
}
@Override
protected void onPause() {
super.onPause();
captureManager.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
captureManager.onDestroy();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
captureManager.onSaveInstanceState(outState);
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
captureManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
return barcodeView.onKeyDown(keyCode, event)||super.onKeyDown(keyCode,event);
}
}
对应的布局文件代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/dbv_my"
android:layout_width="match_parent"
android:layout_height="0dp"
app:zxing_preview_scaling_strategy="fitXY"
android:layout_weight="10"/>
<Button
android:id="@+id/btn_result"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:text="点击查看扫描结果"
android:textSize="20sp"/>
</LinearLayout>
对应的界面样式:(很简单,就是一个l线性布局里面加个扫码控件和一个按钮,根据需要自己定义)
四、连续扫码,点击按钮-显示扫码结果并结束扫码活动。
这个时候我们需要更改下CaptureManager中的部分代码,首先修改returnResult方法:
//返回结果的方法
protected void returnResult(BarcodeResult rawResult) {
Intent intent = resultIntent(rawResult, getBarcodeImagePath(rawResult));
activity.setResult(Activity.RESULT_OK, intent);
// closeAndFinish(); 注释掉后扫码结束不会结束扫码活动
if(barcodeView.getBarcodeView().isCameraClosed()) {
if(null != mResultCallBack){
mResultCallBack.callBack(IntentIntegrator.REQUEST_CODE,Activity.RESULT_OK,intent);
}
} else {
finishWhenClosed = true;
}
// barcodeView.pause();注释掉后扫码返回结果时扫码view不会暂停,继续可以扫描
inactivityTimer.cancel();
}
注释掉的两行很关键,原因已在注释中写明。中间的那几行和下面要增加的接口、属性、方法有关,直接贴出来:
//以下三个是为了在MyCaptureActivity中重写callBack方法
public interface ResultCallBack {
void callBack(int requestCode,int resultCode,Intent intent);
}
private ResultCallBack mResultCallBack;
public void setmResultCallBack(ResultCallBack resultCallBack){
this.mResultCallBack= resultCallBack;
}
作用写的很清楚了,就是为了在自定义的活动中重写callBack方法。
再贴个主活动代码,需要注意的是,使用自定义的界面时,需要增加
.setCaptureActivity(MyCaptureActivity.class)
MainActivity.java
package com.geek66.myzxing;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.google.zxing.integration.android.IntentIntegrator;
public class MainActivity extends AppCompatActivity {
Button button1;//单次扫码
Button button2;//持续扫码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = findViewById(R.id.btn_scan);
button2 = findViewById(R.id.btn_scan2);
//调用系统默认扫码界面
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new IntentIntegrator(MainActivity.this)
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)// 扫码的类型,可选:一维码,二维码,一/二维码
.setPrompt("请对准二维码")// 设置提示语
.setCameraId(0)// 选择摄像头,可使用前置或者后置
.setBeepEnabled(true)// 是否开启声音,扫完码之后会"哔"的一声
.setBarcodeImageEnabled(true)// 扫完码之后生成二维码的图片
.initiateScan();// 初始化扫码
}
});
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new IntentIntegrator(MainActivity.this)
.setCaptureActivity(MyCaptureActivity.class)
.setDesiredBarcodeFormats(IntentIntegrator.QR_CODE)// 扫码的类型,可选:一维码,二维码,一/二维码
.setPrompt("请对准二维码")// 设置提示语
.setCameraId(0)// 选择摄像头,可使用前置或者后置
.setBeepEnabled(true)// 是否开启声音,扫完码之后会"哔"的一声
.setBarcodeImageEnabled(true)// 扫完码之后生成二维码的图片
.initiateScan();// 初始化扫码
}
});
}
}
布局文件:就两个按钮
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<Button
android:id="@+id/btn_scan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击开始扫描二维码"/>
<Button
android:id="@+id/btn_scan2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="自定义界面连续扫码"
/>
</LinearLayout>
我自己做项目用到的,参考了这篇博客(https://blog.****.net/u010618194/article/details/77891313),虽然作者针对这两个功能分析了部分代码,但仍然不是很全面。我自己也没有研究透,以后有新的需求再继续研究。
贴个demo的地址,需要自取: