#过年不停更#HarmonyOS - Zxing-Embedded的使用 原创 精华

中软小助手
发布于 2022-2-15 12:32
浏览
4收藏

春节不停更,此文正在参加「星光计划-春节更帖活动」
作者:庄茂裕

前言:

项目开发中有需要用到扫码识别的功能,这个功能在很多项目中都应该会使用到,于是找到了Zxing-Embedded的鸿蒙版,相信有安卓开发经验的同学都知道这个Zxing-Embedded框架,下面就开始使用

一、ZXing Embedded简介及使用方法

下载地址:https://gitee.com/baijuncheng-open-source/zxing-embedded

安装:

方案一:本地源集成,用户可自定义修改

1.复制zxing_embedded文件夹到project目录;

2.修改设置:在settings.Gradle文件下添加依赖项到这个模块,如下所示

include ':entry', ':zxing-ohos-embedded'

3.例如,我们需要修改build.Gradle文件的入口模块下添加依赖项:

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    testCompile'junit:junit:4.12'
    implementation project('zxing-embeded')
}

方案二:线上HAR包集成(这种方便,不能修改jar包代码)

在本地项目的build.gradled 的 dependencies 下添加

implementation 'com.gitee.baijuncheng-open-source:Zxing-Embedded:1.0.0’ 

然后同步一下sync project whit Gradle files 成功后即安装完毕 (基本上大部分框架都是这样集成)

基本使用:

创建scanner.xml文件,如下

<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
    xmlns:ohos="http://schemas.huawei.com/res/ohos"
    xmlns:ech="http://schemas.huawei.com/res/ohos-auto"
    ohos:height="match_parent"
    ohos:width="match_parent"
    ohos:orientation="vertical">

    <com.google.zxing.journeyapps.barcodescanner.DecoratedBarcodeView
        ohos:id="$+id:zxing_barcode_scanne"
        ohos:height="match_parent"
        ohos:width="match_parent"
        ech:zxing_scanner_layout="$layout:custom_barcode_scanner"/>

</DirectionalLayout>

提醒:导入任何自定义文件或者第三方库的时候必须加

xmlns:ech="http://schemas.huawei.com/res/ohos-auto"

DecoratedBarcodeViewdde的属性简介:

参数 描述
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
app:zxing_preview_scaling_strategy 预览视图的缩放策略,使用centerCrop即可
app:zxing_use_texture_view 是否使用纹理视图(黑色背景)

创建 cusstom_barcode_scammer.xml文件

//BarcodeView提供相机预览功能和图片解码功能
<com.google.zxing.journeyapps.barcodescanner.BarcodeView 
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:id="$+id:zxing_barcode_surface"
    app:zxing_framing_rect_width="250vp"
    app:zxing_framing_rect_height="50vp"/>``

//在BarcodeView视图之上,提供取景框,外部透明背景,扫描激光线
<com.google.zxing.journeyapps.barcodescanner.ViewfinderView
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:id="$+id:zxing_viewfinder_view"
    app:zxing_possible_result_points="$color:zxing_custom_possible_result_points"
    app:zxing_result_view="$color:zxing_custom_result_view"
    app:zxing_viewfinder_laser="$color:zxing_custom_viewfinder_laser"
    app:zxing_viewfinder_laser_visibility="false"
    app:zxing_viewfinder_mask="$color:zxing_custom_viewfinder_mask"/>

创建 scannerAbility文件

public class ScannerAbility extends BaseAbility implements DecoratedBarcodeView.TorchListener, Observable, Component.ClickedListener {
  	//
    private CaptureManager capture;
    private DecoratedBarcodeView barcodeScannerView;
    //闪光灯的 
    private DirectionalLayout switchFlashlightLayout;
    private ViewfinderView viewfinderView;
    private BarcodeView barcodeView;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        //初始化视图
        super.setUIContent(ResourceTable.Layout_ability_scanner);
        initView();
    }

		//初始化视图变量
    private void initView(){
        barcodeScannerView = (DecoratedBarcodeView) findComponentById(ResourceTable.Id_zxing_barcode_scanne);
        barcodeScannerView.setTorchListener(this);
        barcodeView = (BarcodeView) findComponentById(ResourceTable.Id_zxing_barcode_surface);
        /*设置扫描框的宽高*/
        barcodeView.setFramingRectSize(new Size(1000,1000));
        switchFlashlightLayout= (DirectionalLayout) findComponentById(ResourceTable.Id_open_Flashlight);
        switchFlashlightLayout.setClickedListener(this);
        Image back = (Image)findComponentById(ResourceTable.Id_back_icon);
        back.setClickedListener(this);
        viewfinderView = (ViewfinderView) findComponentById(ResourceTable.Id_zxing_viewfinder_view);
        capture = new CaptureManager(this, barcodeScannerView);
        capture.initializeFromIntent(getIntent(), null);
        capture.setShowMissingCameraPermissionDialog(false);
				
      //设置
        changeMaskColor(null);
        changeLaserVisibility(false);
        BusHelper.getINSTANCE().register("CameraPreviewStarted", this);
    }
  
  	//改变背景颜色
    public void changeMaskColor(Component view) {
        int color = Color.argb(80, 0,0,0);
        viewfinderView.setMaskColor(color);
    }

    public void changeLaserVisibility(boolean visible) {
        viewfinderView.setLaserVisibility(visible);
    }



  	//下面控制capture
    @Override
    protected void onActive() {
        super.onActive();
        capture.onResume();
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        capture.onPause();
    }

    @Override
    public void onSaveAbilityState(PacMap outState) {
        super.onSaveAbilityState(outState);
        capture.onSaveInstanceState(outState);
    }

    @Override
    public void onRestoreAbilityState(PacMap inState) {
        super.onRestoreAbilityState(inState);
        capture.initializeFromIntent(getIntent(), inState);
        capture.setShowMissingCameraPermissionDialog(false);
        capture.decode();
    }

    @Override
    protected void onStop() {
        super.onStop();
        BusHelper.getINSTANCE().unRegister(this);
        capture.onDestroy();
    }

		
    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsFromUserResult(requestCode, permissions, grantResults);
        capture.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

	//解码
    @Override
    public void onSubscribe(Object object) {
        if (capture != null)
            capture.decode();
    }
}

扫码识别成功后会返回上个页面,扫码成功后的回调也会在 onAbilityResult里面返回。我这里用到RxBus.getDefault().send方法传递消息,是由于项目用了fraction来承载。

//扫描结果的回调
@Override
protected void onAbilityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode != CUSTOMIZED_REQUEST_CODE && requestCode != REQUEST_CODE) {
        // This is important, otherwise the result will not be passed to the fragment
        super.onAbilityResult(requestCode, resultCode, data);
        return;
    }
    switch (requestCode) {
        case REQUEST_CODE: {
            IntentResult result = IntentIntegrator.parseAbilityResult(requestCode, resultCode, data);
            if (result != null) {
                String toast;
                if (result.getContents() == null) {
                    toast = "Cancelled from fragment";
                } else {
                    toast = "Scanned from fragment: " + result.getContents();
                    // At this point we may or may not have a reference to the activity
                    HashMap parame = new HashMap();
                    parame.put(Constants.EVENT_IN_SCANNER_RESULT,result.getContents());
                    RxBus.getDefault().send(parame, Constants.EVENT_IN_SCANNER_RESULT);
                }
            }
            return;
        }
        default:
            break;
    }
}

效果下图:

#过年不停更#HarmonyOS - Zxing-Embedded的使用-鸿蒙开发者社区

自定义扫描界面

由于Zxing框架的给扫描视图不太符合需求,因此要修改扫描的样式:

需要自定义View(继承ViewfinderView),重写onDraw方法,然后替换掉这里的ViewfinderView。

因为R.layout.zxing_barcode_scanner是源码中的布局文件,无法直接修改,所以还要重写一份布局文件给DecoratedBarcodeView加载,代码如下:



public class CustomViewfinderView extends ViewfinderView {

    /**
     * 重绘时间间隔
     */
    public static final long CUSTOME_ANIMATION_DELAY = 16;


    /* ******************************************    边角线相关属性    ************************************************/

    /**
     * "边角线长度/扫描边框长度"的占比 (比例越大,线越长)
     */
    public float mLineRate = 0.1F;

    /**
     * 边角线厚度 (建议使用dp)
     */
    public float mLineDepth =   4;

    /**
     * 边角线颜色
     */
    public Color mLineColor =  new Color(Color.getIntColor("#1EBB81"));


    public CustomViewfinderView(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        super.onDraw(component, canvas);
      //刷新扫描框的尺寸
        refreshSizes();
        if (framingRect == null || cameraPreview.getPreviewFramingRect() == null) {
            return;
        }
				//获取扫描框的位置
        Rect frame = framingRect;
        Rect previewFrame = cameraPreview.getPreviewFramingRect();
				
        int width = canvas.getLocalClipBounds().getWidth();
        int height = canvas.getLocalClipBounds().getHeight();


        //绘制4个角
        paint.setColor(mLineColor); // 定义画笔的颜色即4个角的颜色
      //画左上角
        canvas.drawRect(frame.left, frame.top, frame.left + frame.getWidth() * mLineRate, frame.top + mLineDepth, paint);
        canvas.drawRect(frame.left, frame.top, frame.left + mLineDepth, frame.top + frame.getHeight() * mLineRate, paint);

		//画右上角
        canvas.drawRect(frame.right - frame.getWidth() * mLineRate, frame.top, frame.right, frame.top + mLineDepth, paint);
        canvas.drawRect(frame.right - mLineDepth, frame.top, frame.right, frame.top + frame.getHeight() * mLineRate, paint);

			//画左下角
        canvas.drawRect(frame.left, frame.bottom - mLineDepth, frame.left + frame.getWidth() * mLineRate, frame.bottom, paint);
        canvas.drawRect(frame.left, frame.bottom - frame.getHeight() * mLineRate, frame.left + mLineDepth, frame.bottom, paint);

			//画右下角
        canvas.drawRect(frame.right - frame.getWidth() * mLineRate, frame.bottom - mLineDepth, frame.right, frame.bottom, paint);
        canvas.drawRect(frame.right - mLineDepth, frame.bottom - frame.getHeight() * mLineRate, frame.right, frame.bottom, paint);


        // 绘制外部(即框架矩形外)变暗
        Color color = new Color(resultBitmap != null ? resultColor : maskColor);
        paint.setColor(color);
        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);
        }
    }
}

代码简介:

(1)onDraw方法中的大部分代码Copy自ViewfinderView,笔者添加部分逻辑:是边角线的绘制。

(2)代码的核心是在onDraw方法的第5行代码:

Rect frame = framingRect;

这个矩阵记录了扫描框四个顶点的坐标,有了这个变量,各位可以发挥想象力自定义自己需要的扫描样式。

接下来,我们用CustomViewfinderView替换掉ViewfinderView(如下所示)

<com.google.zxing.journeyapps.barcodescanner.BarcodeView
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:id="$+id:zxing_barcode_surface"
    app:zxing_framing_rect_width="250vp"
    app:zxing_framing_rect_height="50vp"/>
      
//自定义的view
<com.sgcc.evs.phone.view.CustomViewfinderView
    ohos:width="match_parent"
    ohos:height="match_parent"
    ohos:id="$+id:zxing_viewfinder_view"
    app:zxing_possible_result_points="$color:zxing_custom_possible_result_points"
    app:zxing_result_view="$color:zxing_custom_result_view"
    app:zxing_viewfinder_laser="$color:zxing_custom_viewfinder_laser"
    app:zxing_viewfinder_laser_visibility="false"
    app:zxing_viewfinder_mask="$color:zxing_custom_viewfinder_mask"/>

最后,运行结果如下(如图所示):

#过年不停更#HarmonyOS - Zxing-Embedded的使用-鸿蒙开发者社区

总结

本文简述了zxing-Embeded的鸿蒙版使用,这个库由于现在没有人维护了,有些还需要修复的,闪光灯是用不了的,自定义的扫描样式本文只是提供了一些思路,还有其他的样式修改,也可根据自定义这种方式修改,后期会继续进一步分享优化此框架的问题,欢迎各位鸿蒙开发者一起讨论与研究,共勉。

更多原创内容请关注:中软国际 HarmonyOS 技术团队

入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
分类
6
收藏 4
回复
举报
1条回复
按时间正序
/
按时间倒序
红叶亦知秋
红叶亦知秋

感谢大佬分享使用方法,也希望来个大佬维护一下

已于2022-2-15 14:17:14修改
回复
2022-2-15 14:12:40
回复
    相关推荐