compile 'com.journeyapps:zxing-android-embedded:3.3.0'
<com.journeyapps.barcodescanner.DecoratedBarcodeView
android:id="@+id/scanner"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:zxing_framing_rect_height="@dimen/qr_code_scanner_size"
app:zxing_framing_rect_width="@dimen/qr_code_scanner_size"
app:zxing_scanner_layout="@layout/layout_qrcode_view" />
DecoratedBarcodeView是整个相机图像填充的部分,一般填充全屏。
扫码有效区: app:zxing_framing_rect_height和app:zxing_framing_rect_width两个属性分别限定一个透明区域,即扫码有效区,只有当二维码在有效区内时二维码才会被识别,且有效区不会被ViewfinderView中设定的背景阴影着色;有效区位置恰好在DecoratedBarcodeView范围的正中央。
自定义DecoratedBarcodeView布局:DecoratedBarcodeView有默认的layout来进行布局,也可以通过app:zxing_scanner_layout属性来进行自定义布局,方法是在layout中新建一个xml布局文件,布局文件中主要包含两个重要控件:
public class DecoratedBarcodeView extends FrameLayout {
private BarcodeView barcodeView;
private ViewfinderView viewFinder;
}
BarcodeView控件负责展示相机捕获到的图像,一般为填充全屏
ViewfinderView 控件负责绘制阴影,阴影色不会渲染扫码有效区,一般也设置为填充全屏
<FrameLayout 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">
<com.journeyapps.barcodescanner.BarcodeView
android:id="@+id/zxing_barcode_surface"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/qr_code_scanner_view_finder_margin_top" />
<com.tplink.omada.cloud.ui.addcloudkey.TPScannerView
android:id="@+id/zxing_viewfinder_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="@dimen/qr_code_scanner_view_finder_margin_top"
app:zxing_viewfinder_mask="@color/black_46" />
FrameLayout>
ViewfinderView绘制的阴影颜色由app:zxing_viewfinder_mask属性来控制
1)动态申请相机权限:
private boolean checkPermission() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PERMISSION_GRANTED) {
isSystemPermissionDialogShow = true;
ActivityCompat.requestPermissions(ScannerActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
return false;
}
return true;
}
2)建立一个CaptureManager
public class MyCaptureManager extends CaptureManager {
private QRCodeCallBack callBack;
public MyCaptureManager(Activity activity, DecoratedBarcodeView barcodeView) {
super(activity, barcodeView);
}
@Override
protected void returnResult(BarcodeResult rawResult) {
if (callBack != null) {
callBack.handle(rawResult.getText());
}
}
public void setCallBack(QRCodeCallBack callBack) {
this.callBack = callBack;
}
public interface QRCodeCallBack {
void handle(String result);
}
}
3)添加对扫码结果的回调:
captureManager = new TPCaptureManager(this, binding.scanner);
captureManager.setCallBack(qrResult -> {
//doSomething
});
其中qrResult就是扫码得到的字符串,通过回调对扫码结果进行处理。
4)扫描结果的处理:
如果要求扫描得到的结果要在ScannerActivity处理扫描结果,会发现扫描一个二维码之后相机图像会停止刷新,扫码有效区也会失效,即扫码框默认是一次性使用的,所以要实现一个扫码框多次使用要在每次扫码结束后调用:
decoratedBarcodeView.resume();
captureManager.decode();
此外,在ScannerActivity的onResume中也要加入:
if (captureManager != null) {
captureManager.onResume();
captureManager.decode();
decoratedBarcodeView.resume();
}
captureManager的生命周期跟随Activity的生命周期,即Activity执行onPause(),captrueManager也要显示的手动执行onPause()
protected void onPause() {
super.onPause();
if (captureManager != null) {
captureManager.onPause();
}
}
扫码后立即返回上一页面,并向上一页面报告扫码得到的字符串:
打开ScannerActivity:
private void startQrCode() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.CAMERA}, 1);
return;
}
new IntentIntegrator(this).setOrientationLocked(false)
.setCaptureActivity(ScannerActivity.class) // 设置自定义的activity是ScanActivity
.initiateScan(); // 初始化扫描
}
处理扫描结果:
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}