更新CameraX至v1.2.1
This commit is contained in:
192
README.md
192
README.md
@@ -24,8 +24,9 @@ ZXingLite for Android 是ZXing的精简极速版,基于ZXing库优化扫码和
|
||||
|
||||
|
||||
## ViewfinderView属性说明
|
||||
| 属性 | 值类型 | 默认值 | 说明 |
|
||||
| :------| :------ | :------ | :------ |
|
||||
|
||||
| 属性 | 属性类型 | 默认值 | 属性说明 |
|
||||
| :------|:----------| :------ | :------ |
|
||||
| maskColor | color |<font color=#000000>#60000000</font>| 扫描区外遮罩的颜色 |
|
||||
| frameColor | color |<font color=#1FB3E2>#7F1FB3E2</font>| 扫描区边框的颜色 |
|
||||
| cornerColor | color |<font color=#1FB3E2>#FF1FB3E2</font>| 扫描区边角的颜色 |
|
||||
@@ -53,6 +54,14 @@ ZXingLite for Android 是ZXing的精简极速版,基于ZXing库优化扫码和
|
||||
| framePaddingRight | dimension | 0 | 扫码框右边的内间距 |
|
||||
| framePaddingBottom | dimension | 0 | 扫码框下边的内间距 |
|
||||
| frameGravity | enum | center | 扫码框对齐方式 |
|
||||
| pointColor | color | <font color=#1FB3E2>#FF1FB3E2</font> | 结果点的颜色 |
|
||||
| pointStrokeColor | color | <font color=#FFFFFF>#FFFFFFFF</font> | 结果点描边的颜色 |
|
||||
| pointRadius | dimension | 15dp | 结果点的半径 |
|
||||
| pointStrokeRatio | float | 1.2 | 结果点描边半径与结果点半径的比例 |
|
||||
| pointDrawable | reference | | 结果点自定义图片 |
|
||||
| showPointAnim | boolean | true | 是否显示结果点的动画 |
|
||||
| laserDrawable | reference | | 扫描激光自定义图片 |
|
||||
| viewfinderStyle | enum | classic | 取景框样式;支持:classic:经典样式(带扫码框那种)、popular:流行样式(不带扫码框) |
|
||||
|
||||
|
||||
## 引入
|
||||
@@ -74,7 +83,7 @@ allprojects {
|
||||
|
||||
```gradle
|
||||
// AndroidX 版本
|
||||
implementation 'com.github.jenly1314:zxing-lite:2.3.0'
|
||||
implementation 'com.github.jenly1314:zxing-lite:2.3.1'
|
||||
|
||||
```
|
||||
|
||||
@@ -96,74 +105,68 @@ implementation 'com.king.zxing:zxing-lite:1.1.9-androidx'
|
||||
implementation 'com.king.zxing:zxing-lite:1.1.9'
|
||||
```
|
||||
|
||||
## 使用说明
|
||||
|
||||
### 快速实现扫码有以下几种方式:
|
||||
### 快速实现扫码识别有以下几种方式:
|
||||
|
||||
> 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
|
||||
> 1、直接使用CaptureActivity或者CaptureFragment。(默认的扫码实现)
|
||||
|
||||
> 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。(适用于大多场景,并无需关心扫码相关逻辑,自定义布局时需覆写getLayoutId方法)实现示例:[CustomCaptureActivity](app/src/main/java/com/king/zxing/app/CustomCaptureActivity.java) 和 [QRCodeActivity](app/src/main/java/com/king/zxing/app/QRCodeActivity.java)
|
||||
|
||||
> 3、在你项目的Activity或者Fragment中实例化一个CameraScan即可。(适用于想在扫码界面写交互逻辑,又因为项目架构或其它原因,无法直接或间接继承CaptureActivity或CaptureFragment时使用)实现示例:[CustomActivity](app/src/main/java/com/king/zxing/app/CustomActivity.java)
|
||||
> 3、在你项目的Activity或者Fragment中实例化一个CameraScan即可。(适用于想在扫码界面写交互逻辑,又因为项目架构或其它原因,无法直接或间接继承CaptureActivity或CaptureFragment时使用)实现示例:[CustomFullScanActivity](app/src/main/java/com/king/zxing/app/CustomFullScanActivity.java)
|
||||
|
||||
> 4、继承CameraScan自己实现一个,可参照默认实现类DefaultCameraScan,其它步骤同方式3。(扩展高级用法,谨慎使用)
|
||||
|
||||
### 关于 CameraScan
|
||||
|
||||
## 示例
|
||||
**CameraScan** 作为相机扫描的(核心)基类;所有与相机扫描相关的都是基于此类来直接或间接进行控制的。
|
||||
|
||||
布局示例
|
||||
> 可自定义布局(覆写getLayoutId方法),布局内至少要保证有PreviewView。
|
||||
### 关于 CameraConfig
|
||||
|
||||
> PreviewView 用来预览,布局内至少要保证有PreviewView,如果是继承CaptureActivity或CaptureFragment,控件id可覆写getPreviewViewId方法自定义
|
||||
主要是相机相关的配置;如:摄像头的前置后置、相机预览相关、图像分析相关等配置。
|
||||
|
||||
> ViewfinderView 用来渲染扫码视图,给用户起到一个视觉效果,本身扫码识别本身没有关系,如果是继承CaptureActivity或CaptureFragment,控件id可复写getViewfinderViewId方法自定义,默认为previewView,返回0表示无需ViewfinderView
|
||||
> 你可以直接库中内置实现的相机配置: **CameraConfig** 、**AspectRatioCameraConfig** 和 **ResolutionCameraConfig**。
|
||||
|
||||
> ivFlashlight 用来内置手电筒,如果是继承CaptureActivity或CaptureFragment,控件id可复写getFlashlightId方法自定义,默认为ivFlashlight。返回0表示无需内置手电筒。您也可以自己去定义
|
||||
#### 这里简单说下各自的特点:
|
||||
|
||||
* **CameraConfig**:默认的相机配置。
|
||||
* **AspectRatioCameraConfig**:根据纵横比配置相机,使输出分析的图像尽可能的接近屏幕的比例
|
||||
* **ResolutionCameraConfig**:根据尺寸配置相机的目标图像大小,使输出分析的图像的分辨率尽可能的接近屏幕尺寸
|
||||
|
||||
```Xml
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/previewView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
<ImageView
|
||||
android:id="@+id/ivFlashlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/zxl_flashlight_selector"
|
||||
android:layout_marginTop="@dimen/zxl_flashlight_margin_top" />
|
||||
</FrameLayout>
|
||||
```
|
||||
> 你也可以自定义或覆写 **CameraConfig** 中的 **options** 方法,根据需要定制配置。
|
||||
|
||||
或在你的布局中添加
|
||||
这里特别温馨提示:默认配置在未配置相机的目标分析图像大小时,会优先使用:横屏:640 * 480 竖屏:480 * 640;
|
||||
|
||||
```Xml
|
||||
<include layout="@layout/zxl_capture"/>
|
||||
```
|
||||
根据这个图像质量顺便说下默认配置的优缺点:
|
||||
|
||||
代码示例 (二维码/条形码)
|
||||
```Java
|
||||
//跳转的默认扫码界面
|
||||
startActivityForResult(new Intent(context,CaptureActivity.class),requestCode);
|
||||
* 优点:因为图像质量不高,所以在低配置的设备上使用也能hold住,这样就能尽可能的适应各种设备;
|
||||
* 缺点:正是由于图像质量不高,从而可能会对检测识别率略有影响,比如在某些机型上体验欠佳。
|
||||
* 结论:在适配、性能与体验之间得有所取舍,找到平衡点。
|
||||
|
||||
//生成二维码
|
||||
CodeUtils.createQRCode(content,600,logo);
|
||||
//生成条形码
|
||||
CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200);
|
||||
//解析条形码/二维码
|
||||
CodeUtils.parseCode(bitmap);
|
||||
//解析二维码
|
||||
CodeUtils.parseQRCode(bitmap);
|
||||
```
|
||||
> 当使用默认的 **CameraConfig** 在某些机型上体验欠佳时,你可以尝试使用 **AspectRatioCameraConfig** 或
|
||||
**ResolutionCameraConfig** 会有意想不到奇效。
|
||||
|
||||
### 关于 **Analyzer**
|
||||
|
||||
**Analyzer** 为定义的分析器接口;主要用于分析相机预览的帧数据;通过实现 **Analyzer** 可以自定义分析过程。
|
||||
|
||||
### 关于 **CaptureActivity** 和 **CaptureFragment**
|
||||
|
||||
**CaptureActivity** 和 **CaptureFragment** 作为扫描预览界面的基类,主要目的是便于快速实现扫码识别。
|
||||
|
||||
> 扫描预览界面内部持有 **CameraScan**,并处理了 **CameraScan** 的初始化(如:相机权限、相机预览、生命周期等细节)
|
||||
|
||||
## 使用示例
|
||||
|
||||
### CameraScan配置示例
|
||||
|
||||
**CameraScan** 里面包含部分支持链式调用的方法,即调用返回是 **CameraScan** 本身的一些配置建议在调用 **startCamera()** 方法之前调用。
|
||||
|
||||
> 如果是通过继承 **CaptureActivity** 或者 **CaptureFragment** 或其子类实现的相机扫描,可以在
|
||||
**initCameraScan()** 方法中获取 **CameraScan** ,然后根据需要修改相关配置。
|
||||
|
||||
示例1:
|
||||
|
||||
CameraScan配置示例
|
||||
```java
|
||||
//获取CameraScan,扫码相关的配置设置。CameraScan里面包含部分支持链式调用的方法,即调用返回是CameraScan本身的一些配置建议在startCamera之前调用。
|
||||
getCameraScan().setPlayBeep(true)//设置是否播放音效,默认为false
|
||||
@@ -176,16 +179,17 @@ CameraScan配置示例
|
||||
.bindFlashlightView(ivFlashlight)//绑定手电筒,绑定后可根据光线传感器,动态显示或隐藏手电筒按钮
|
||||
.setOnScanResultCallback(this)//设置扫码结果回调,需要自己处理或者需要连扫时,可设置回调,自己去处理相关逻辑
|
||||
.setAnalyzer(new MultiFormatAnalyzer(new DecodeConfig()))//设置分析器,DecodeConfig可以配置一些解码时的配置信息,如果内置的不满足您的需求,你也可以自定义实现,
|
||||
.setAnalyzeImage(true)//设置是否分析图片,默认为true。如果设置为false,相当于关闭了扫码识别功能
|
||||
.startCamera();//启动预览(如果是通过继承CaptureActivity或CaptureFragment实现扫码无需调用这句startCamera)
|
||||
.setAnalyzeImage(true);//设置是否分析图片,默认为true。如果设置为false,相当于关闭了扫码识别功能
|
||||
|
||||
// 启动预览(如果是通过继承CaptureActivity或CaptureFragment实现的则无需调用startCamera)
|
||||
getCameraScan().startCamera();
|
||||
|
||||
// 设置闪光灯(手电筒)是否开启,需在startCamera之后调用才有效
|
||||
getCameraScan().enableTorch(torch);
|
||||
|
||||
```
|
||||
|
||||
CameraScan配置示例(只需识别二维码的配置示例)
|
||||
示例2:(只需识别二维码的配置示例)
|
||||
```java
|
||||
//初始化解码配置
|
||||
DecodeConfig decodeConfig = new DecodeConfig();
|
||||
@@ -201,7 +205,65 @@ CameraScan配置示例(只需识别二维码的配置示例)
|
||||
.setAnalyzer(new MultiFormatAnalyzer(decodeConfig));//设置分析器,如果内置实现的一些分析器不满足您的需求,你也可以自定义去实现
|
||||
```
|
||||
|
||||
通过继承CaptureActivity实现扫二维码完整示例
|
||||
### 布局示例
|
||||
|
||||
**PreviewView** 用来预览,布局内至少要保证有 **PreviewView**,如果是继承 **CaptureActivity** 或 **CaptureFragment**,控件id可覆写`getPreviewViewId`方法自定义
|
||||
|
||||
**ViewfinderView** 用来渲染扫码视图,给用户起到一个视觉效果,本身扫码识别本身没有关系,如果是继承 **CaptureActivity** 或 **CaptureFragment**,控件ID可复写`getViewfinderViewId`方法自定义,默认为 **previewView**,返回0表示无需 **ViewfinderView**
|
||||
|
||||
**ivFlashlight** 是布局内置的手电筒,如果是继承 **CaptureActivity** 或 **CaptureFragment**,控件id可复写`getFlashlightId`方法自定义,默认为 **ivFlashlight**。返回0表示无需内置手电筒。您也可以自己去定义
|
||||
|
||||
> 可自定义布局(覆写`getLayoutId方法`),布局内至少要保证有 **PreviewView**。
|
||||
|
||||
```Xml
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.camera.view.PreviewView
|
||||
android:id="@+id/previewView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFlashlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="@dimen/zxl_flashlight_margin_top"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/zxl_flashlight_selector" />
|
||||
</FrameLayout>
|
||||
```
|
||||
|
||||
或在你的布局中添加
|
||||
|
||||
```Xml
|
||||
<include layout="@layout/zxl_capture"/>
|
||||
```
|
||||
|
||||
### 代码示例
|
||||
|
||||
**工具类CodeUtils的使用示例(二维码/条形码)**
|
||||
```Java
|
||||
|
||||
// 生成二维码
|
||||
CodeUtils.createQRCode(content,600,logo);
|
||||
// 生成条形码
|
||||
CodeUtils.createBarCode(content, BarcodeFormat.CODE_128,800,200);
|
||||
// 解析条形码/二维码
|
||||
CodeUtils.parseCode(bitmap);
|
||||
// 解析二维码
|
||||
CodeUtils.parseQRCode(bitmap);
|
||||
```
|
||||
|
||||
**通过继承CaptureActivity实现扫二维码完整示例**
|
||||
|
||||
```java
|
||||
public class QRCodeActivity extends CaptureActivity {
|
||||
|
||||
@@ -259,16 +321,19 @@ public class QRCodeActivity extends CaptureActivity {
|
||||
|
||||
```
|
||||
|
||||
如果直接使用CaptureActivity需在您项目的AndroidManifest中添加如下配置
|
||||
|
||||
### 其他
|
||||
|
||||
#### AndroidManifest
|
||||
|
||||
如果你直接使用了默认 **CaptureActivity** ,则需在你项目的AndroidManifest中注册 **CaptureActivity**,配置如下
|
||||
```Xml
|
||||
<activity
|
||||
android:name="com.king.zxing.CaptureActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/CaptureTheme"/>
|
||||
```
|
||||
|
||||
|
||||
### 其他
|
||||
#### JDK版本
|
||||
|
||||
需使用JDK8+编译,在你项目中的build.gradle的android{}中添加配置:
|
||||
|
||||
@@ -290,7 +355,7 @@ compileOptions {
|
||||
|
||||
## 版本说明
|
||||
|
||||
### v2.x 基于CameraX重构震撼发布
|
||||
### v2.x 基于CameraX进行了重构
|
||||
|
||||
#### v2.x 相对于 v1.x 的优势
|
||||
|
||||
@@ -304,7 +369,7 @@ compileOptions {
|
||||
|
||||
#### v1.x 说明
|
||||
|
||||
[【v1.1.9】](https://github.com/jenly1314/ZXingLite/tree/androidx) 如果您正在使用 **1.x** 版本请点击下面的链接查看分支版本,当前 **2.x** 版本已经基于 **CameraX** 进行重构,不支持升级,请在新项目中使用。
|
||||
[【v1.1.9】](https://github.com/jenly1314/ZXingLite/tree/androidx) 如果您正在使用 **1.x** 版本请点击下面的链接查看分支版本,当前 **2.x** 版本已经基于 **CameraX** 进行重构,API变化较大,谨慎升级。
|
||||
|
||||
查看AndroidX版 **1.x** 分支 [请戳此处](https://github.com/jenly1314/ZXingLite/tree/androidx)
|
||||
|
||||
@@ -314,6 +379,11 @@ compileOptions {
|
||||
|
||||
## 版本记录
|
||||
|
||||
#### v2.3.1:2023-3-4
|
||||
* 更新CameraX至v1.2.1
|
||||
* 更新Gradle至v7.5
|
||||
* 优化细节
|
||||
|
||||
#### v2.3.0:2022-12-11
|
||||
* 更新CameraX至v1.2.0
|
||||
* 更新zxing至v3.5.1
|
||||
|
||||
@@ -26,8 +26,8 @@ android {
|
||||
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
|
||||
// kotlinOptions {
|
||||
|
||||
Binary file not shown.
@@ -11,8 +11,8 @@
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 35,
|
||||
"versionName": "2.3.0",
|
||||
"versionCode": 36,
|
||||
"versionName": "2.3.1",
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
],
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
android:theme="@style/CaptureTheme"/>
|
||||
|
||||
<activity
|
||||
android:name=".CustomActivity"
|
||||
android:name=".CustomFullScanActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/CaptureTheme"/>
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.CameraScan;
|
||||
import com.king.zxing.config.CameraConfig;
|
||||
import com.king.zxing.CaptureActivity;
|
||||
import com.king.zxing.DecodeConfig;
|
||||
import com.king.zxing.DecodeFormatManager;
|
||||
@@ -121,8 +120,8 @@ public class CustomCaptureActivity extends CaptureActivity {
|
||||
if(toast == null){
|
||||
toast = Toast.makeText(this,text,Toast.LENGTH_SHORT);
|
||||
}else{
|
||||
toast.setDuration(Toast.LENGTH_SHORT);
|
||||
toast.setText(text);
|
||||
toast.setDuration(Toast.LENGTH_SHORT);
|
||||
}
|
||||
toast.show();
|
||||
}
|
||||
|
||||
@@ -8,9 +8,13 @@ import android.widget.Toast;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
import com.king.zxing.CameraScan;
|
||||
import com.king.zxing.DecodeConfig;
|
||||
import com.king.zxing.DecodeFormatManager;
|
||||
import com.king.zxing.DefaultCameraScan;
|
||||
import com.king.zxing.ViewfinderView;
|
||||
import com.king.zxing.analyze.MultiFormatAnalyzer;
|
||||
import com.king.zxing.app.util.StatusBarUtils;
|
||||
import com.king.zxing.config.ResolutionCameraConfig;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
@@ -22,7 +26,7 @@ import androidx.fragment.app.Fragment;
|
||||
* 自定义扫码,切记自定义扫码需在{@link Activity}或者{@link Fragment}相对应的生命周期里面调用{@link #mCameraScan}对应的生命周期
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CustomActivity extends AppCompatActivity implements CameraScan.OnScanResultCallback {
|
||||
public class CustomFullScanActivity extends AppCompatActivity implements CameraScan.OnScanResultCallback {
|
||||
|
||||
private boolean isContinuousScan;
|
||||
|
||||
@@ -59,9 +63,16 @@ public class CustomActivity extends AppCompatActivity implements CameraScan.OnSc
|
||||
|
||||
isContinuousScan = getIntent().getBooleanExtra(MainActivity.KEY_IS_CONTINUOUS,false);
|
||||
|
||||
//初始化解码配置
|
||||
DecodeConfig decodeConfig = new DecodeConfig();
|
||||
decodeConfig.setHints(DecodeFormatManager.QR_CODE_HINTS)//如果只有识别二维码的需求,这样设置效率会更高,不设置默认为DecodeFormatManager.DEFAULT_HINTS
|
||||
.setFullAreaScan(true);//设置是否全区域识别,默认false
|
||||
|
||||
mCameraScan = new DefaultCameraScan(this,previewView);
|
||||
mCameraScan.setOnScanResultCallback(this)
|
||||
.setAnalyzer(new MultiFormatAnalyzer(decodeConfig))
|
||||
.setVibrate(true)
|
||||
.setCameraConfig(new ResolutionCameraConfig(this, ResolutionCameraConfig.IMAGE_QUALITY_720P))
|
||||
.startCamera();
|
||||
|
||||
}
|
||||
@@ -31,7 +31,6 @@ import com.king.zxing.util.CodeUtils;
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@@ -43,9 +42,9 @@ import pub.devrel.easypermissions.EasyPermissions;
|
||||
/**
|
||||
* 扫码Demo示例说明
|
||||
*
|
||||
* 快速实现扫码有以下几种方式:
|
||||
* 快速实现扫码识别有以下几种方式:
|
||||
*
|
||||
* 1、直接使用CaptureActivity或者CaptureFragment。(纯洁的扫码,无任何添加剂)
|
||||
* 1、直接使用CaptureActivity或者CaptureFragment。(默认的扫码实现)
|
||||
*
|
||||
* 2、通过继承CaptureActivity或者CaptureFragment并自定义布局。(适用于大多场景,并无需关心扫码相关逻辑,自定义布局时需覆写getLayoutId方法)
|
||||
*
|
||||
@@ -108,13 +107,6 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
|
||||
}
|
||||
|
||||
private void parsePhoto(Intent data){
|
||||
|
||||
// final String path = UriUtils.getImagePath(this,data);
|
||||
// LogUtils.d("path:" + path);
|
||||
// if(TextUtils.isEmpty(path)){
|
||||
// return;
|
||||
// }
|
||||
|
||||
try {
|
||||
Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(),data.getData());
|
||||
//异步解析
|
||||
@@ -243,7 +235,7 @@ public class MainActivity extends AppCompatActivity implements EasyPermissions.P
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
case R.id.btn4:
|
||||
this.cls = CustomActivity.class;
|
||||
this.cls = CustomFullScanActivity.class;
|
||||
this.title = ((Button)v).getText().toString();
|
||||
checkCameraPermissions();
|
||||
break;
|
||||
|
||||
@@ -11,6 +11,7 @@ import com.king.zxing.DecodeConfig;
|
||||
import com.king.zxing.DecodeFormatManager;
|
||||
import com.king.zxing.analyze.MultiFormatAnalyzer;
|
||||
import com.king.zxing.app.util.StatusBarUtils;
|
||||
import com.king.zxing.config.AspectRatioCameraConfig;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
@@ -50,8 +51,8 @@ public class QRCodeActivity extends CaptureActivity {
|
||||
|
||||
//在启动预览之前,设置分析器,只识别二维码
|
||||
getCameraScan()
|
||||
.setCameraConfig(new AspectRatioCameraConfig(this))//设置相机配置,使用 AspectRatioCameraConfig
|
||||
.setVibrate(true)//设置是否震动,默认为false
|
||||
.setNeedAutoZoom(true)//二维码太小时可自动缩放,默认为false
|
||||
.setAnalyzer(new MultiFormatAnalyzer(decodeConfig));//设置分析器,如果内置实现的一些分析器不满足您的需求,你也可以自定义去实现
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:drawable="@drawable/flash_on"/>
|
||||
<item android:state_selected="false" android:drawable="@drawable/flash_off"/>
|
||||
</selector>
|
||||
@@ -87,7 +87,7 @@
|
||||
android:layout_marginRight="20dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:text="自定义扫码"
|
||||
android:text="自定义全屏扫二维码"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/btn3"
|
||||
|
||||
@@ -13,24 +13,16 @@
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:labelTextWidth="180dp"
|
||||
app:labelText="@string/tips_scan_code"
|
||||
app:labelTextSize="@dimen/size_14sp"
|
||||
app:laserColor="@color/colorAccent"
|
||||
app:frameColor="@color/colorPrimary"
|
||||
app:cornerColor="@color/colorPrimary"
|
||||
app:labelTextLocation="bottom"
|
||||
app:laserStyle="grid"
|
||||
app:gridHeight="0dp"/>
|
||||
app:viewfinderStyle="popular"/>
|
||||
<ImageView
|
||||
android:id="@+id/ivFlash"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/flash_selected_selector"
|
||||
android:src="@drawable/zxl_flashlight_selector"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="160dp" />
|
||||
android:layout_marginTop="170dp" />
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -24,11 +24,11 @@
|
||||
android:id="@+id/ivFlashlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/flash_selected_selector"
|
||||
android:src="@drawable/zxl_flashlight_selector"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="160dp" />
|
||||
android:layout_marginTop="170dp" />
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -24,11 +24,11 @@
|
||||
android:id="@+id/ivFlashlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/flash_selected_selector"
|
||||
android:src="@drawable/zxl_flashlight_selector"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_marginTop="160dp" />
|
||||
android:layout_marginTop="170dp" />
|
||||
<include layout="@layout/toolbar_capture"/>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -1,4 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="status_bar_height">25dp</dimen>
|
||||
</resources>
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="status_bar_height">0dp</dimen>
|
||||
<dimen name="status_bar_height">25dp</dimen>
|
||||
|
||||
<dimen name="title_height">50dp</dimen>
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@ buildscript {
|
||||
|
||||
repositories {
|
||||
google()
|
||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -24,9 +23,7 @@ buildscript {
|
||||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
maven { url 'https://maven.aliyun.com/repository/public/' }
|
||||
mavenCentral()
|
||||
// jcenter() // Warning: this repository is going to shut down soon
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
## 版本记录
|
||||
|
||||
#### v2.3.1:2023-3-4
|
||||
* 更新CameraX至v1.2.1
|
||||
* 更新Gradle至v7.5
|
||||
* 优化细节
|
||||
|
||||
#### v2.3.0:2022-12-11
|
||||
* 更新CameraX至v1.2.0
|
||||
* 更新zxing至v3.5.1
|
||||
@@ -20,6 +25,7 @@
|
||||
#### v2.1.0:2021-6-30 (从v2.1.0开始不再发布至JCenter)
|
||||
* 更新CameraX至v1.0.0
|
||||
* 优化细节
|
||||
* 发布至MavenCentral
|
||||
|
||||
#### v2.0.3:2021-3-26
|
||||
* 更新CameraX至v1.0.0-rc03
|
||||
|
||||
@@ -14,8 +14,8 @@ org.gradle.jvmargs = -Xmx1536m
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
|
||||
VERSION_NAME=2.3.0
|
||||
VERSION_CODE=35
|
||||
VERSION_NAME=2.3.1
|
||||
VERSION_CODE=36
|
||||
GROUP=com.github.jenly1314
|
||||
|
||||
POM_DESCRIPTION=ZXingLite for Android
|
||||
@@ -43,3 +43,5 @@ RELEASE_SIGNING_ENABLED=false
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//App
|
||||
def app_version = [:]
|
||||
app_version.versionCode = 35
|
||||
app_version.versionName = "2.3.0"
|
||||
app_version.versionCode = 36
|
||||
app_version.versionName = "2.3.1"
|
||||
ext.app_version = app_version
|
||||
|
||||
//build version
|
||||
@@ -29,14 +29,14 @@ versions.espresso = "3.2.0"
|
||||
|
||||
versions.bintray_release = "0.9.2"
|
||||
versions.mavenPublish = '0.18.0'
|
||||
versions.gralde = "7.1.1"
|
||||
versions.gralde = "7.4.1"
|
||||
versions.kotlin = "1.6.0"
|
||||
versions.coreKtx = "1.6.0"
|
||||
|
||||
//zxing
|
||||
versions.zxing = "3.5.1"
|
||||
|
||||
versions.camerax = "1.2.0"
|
||||
versions.camerax = "1.2.1"
|
||||
|
||||
versions.easypermissions = "3.0.0"
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
sourceCompatibility JavaVersion.VERSION_11
|
||||
targetCompatibility JavaVersion.VERSION_11
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,18 +16,36 @@ import androidx.annotation.Nullable;
|
||||
import androidx.camera.core.CameraSelector;
|
||||
|
||||
/**
|
||||
* 相机扫描基类定义;内置的默认实现见:{@link DefaultCameraScan}
|
||||
* <p>
|
||||
* 快速实现扫描识别主要有以下几种方式:
|
||||
* <p>
|
||||
* 1、通过继承 {@link CaptureActivity}或者{@link CaptureFragment}或其子类,可快速实现扫描识别。
|
||||
* (适用于大多数场景,自定义布局时需覆写getLayoutId方法)
|
||||
* <p>
|
||||
* 2、在你项目的Activity或者Fragment中实例化一个{@link DefaultCameraScan}。(适用于想在扫码界面写交互逻辑,又因为项目
|
||||
* 架构或其它原因,无法直接或间接继承{@link CaptureActivity}或{@link CaptureFragment}时使用)
|
||||
* <p>
|
||||
* 3、继承{@link CameraScan}自己实现一个,可参照默认实现类{@link DefaultCameraScan},其他步骤同方式2。(高级用法,谨慎使用)
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public abstract class CameraScan implements ICamera, ICameraControl {
|
||||
|
||||
/**
|
||||
* 扫描返回结果的key;解析方式可参见:{@link #parseScanResult(Intent)}
|
||||
*/
|
||||
public static String SCAN_RESULT = "SCAN_RESULT";
|
||||
|
||||
/** A camera on the device facing the same direction as the device's screen. */
|
||||
/**
|
||||
* A camera on the device facing the same direction as the device's screen.
|
||||
*/
|
||||
public static int LENS_FACING_FRONT = CameraSelector.LENS_FACING_FRONT;
|
||||
/** A camera on the device facing the opposite direction as the device's screen. */
|
||||
/**
|
||||
* A camera on the device facing the opposite direction as the device's screen.
|
||||
*/
|
||||
public static int LENS_FACING_BACK = CameraSelector.LENS_FACING_BACK;
|
||||
|
||||
|
||||
/**
|
||||
* 是否需要支持自动缩放
|
||||
*/
|
||||
@@ -40,15 +58,16 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
|
||||
/**
|
||||
* 是否需要支持触摸缩放
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean isNeedTouchZoom() {
|
||||
return isNeedTouchZoom;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置是否需要支持触摸缩放
|
||||
*
|
||||
* @param needTouchZoom
|
||||
* @return
|
||||
*/
|
||||
@@ -59,6 +78,7 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
|
||||
/**
|
||||
* 是否需要支持自动缩放
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
protected boolean isNeedAutoZoom() {
|
||||
@@ -67,6 +87,7 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
|
||||
/**
|
||||
* 设置是否需要支持自动缩放
|
||||
*
|
||||
* @param needAutoZoom
|
||||
* @return
|
||||
*/
|
||||
@@ -77,19 +98,21 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
|
||||
/**
|
||||
* 设置相机配置,请在{@link #startCamera()}之前调用
|
||||
*
|
||||
* @param cameraConfig
|
||||
*/
|
||||
public abstract CameraScan setCameraConfig(CameraConfig cameraConfig);
|
||||
|
||||
/**
|
||||
* 设置是否分析图像,通过此方法可以动态控制是否分析图像,常用于中断扫码识别。如:连扫时,扫到结果,然后停止分析图像
|
||||
*
|
||||
* <p>
|
||||
* 1. 因为分析图像默认为true,如果想支持连扫,在{@link OnScanResultCallback#onScanResultCallback(Result)}返回true拦截即可。
|
||||
* 当连扫的处理逻辑比较复杂时,请在处理逻辑前通过调用setAnalyzeImage(false)来停止分析图像,
|
||||
* 等逻辑处理完后再调用getCameraScan().setAnalyzeImage(true)来继续分析图像。
|
||||
*
|
||||
* <p>
|
||||
* 2. 如果只是想拦截扫码结果回调自己处理逻辑,但并不想继续分析图像(即不想连扫),可通过
|
||||
* 调用getCameraScan().setAnalyzeImage(false)来停止分析图像。
|
||||
*
|
||||
* @param analyze
|
||||
*/
|
||||
public abstract CameraScan setAnalyzeImage(boolean analyze);
|
||||
@@ -97,51 +120,56 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
/**
|
||||
* 设置分析器,如果内置的一些分析器不满足您的需求,你也可以自定义{@link Analyzer},
|
||||
* 自定义时,切记需在{@link #startCamera()}之前调用才有效。
|
||||
*
|
||||
* <p>
|
||||
* 内置了一些{@link Analyzer}的实现类如下:
|
||||
*
|
||||
* @param analyzer
|
||||
* @see {@link MultiFormatAnalyzer}
|
||||
* @see {@link AreaRectAnalyzer}
|
||||
* @see {@link ImageAnalyzer}
|
||||
*
|
||||
* @see {@link BarcodeFormatAnalyzer}
|
||||
* @see {@link QRCodeReader}
|
||||
*
|
||||
* @param analyzer
|
||||
*/
|
||||
public abstract CameraScan setAnalyzer(Analyzer analyzer);
|
||||
|
||||
/**
|
||||
* 设置是否震动
|
||||
*
|
||||
* @param vibrate
|
||||
*/
|
||||
public abstract CameraScan setVibrate(boolean vibrate);
|
||||
|
||||
/**
|
||||
* 设置是否播放提示音
|
||||
*
|
||||
* @param playBeep
|
||||
*/
|
||||
public abstract CameraScan setPlayBeep(boolean playBeep);
|
||||
|
||||
/**
|
||||
* 设置扫码结果回调
|
||||
*
|
||||
* @param callback
|
||||
*/
|
||||
public abstract CameraScan setOnScanResultCallback(OnScanResultCallback callback);
|
||||
|
||||
/**
|
||||
* 绑定手电筒,绑定后可根据光线传感器,动态显示或隐藏手电筒
|
||||
*
|
||||
* @param v
|
||||
*/
|
||||
public abstract CameraScan bindFlashlightView(@Nullable View v);
|
||||
|
||||
/**
|
||||
* 设置光线足够暗的阈值(单位:lux),需要通过{@link #bindFlashlightView(View)}绑定手电筒才有效
|
||||
*
|
||||
* @param lightLux
|
||||
*/
|
||||
public abstract CameraScan setDarkLightLux(float lightLux);
|
||||
|
||||
/**
|
||||
* 设置光线足够明亮的阈值(单位:lux),需要通过{@link #bindFlashlightView(View)}绑定手电筒才有效
|
||||
*
|
||||
* @param lightLux
|
||||
*/
|
||||
public abstract CameraScan setBrightLightLux(float lightLux);
|
||||
@@ -149,13 +177,13 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
public interface OnScanResultCallback {
|
||||
/**
|
||||
* 扫码结果回调
|
||||
*
|
||||
* @param result
|
||||
* @return 返回false表示不拦截,将关闭扫码界面并将结果返回给调用界面;
|
||||
* 返回true表示拦截,需自己处理逻辑。当isAnalyze为true时,默认会继续分析图像(也就是连扫)。
|
||||
* 如果只是想拦截扫码结果回调,并不想继续分析图像(不想连扫),请在拦截扫码逻辑处通过调
|
||||
* 用{@link CameraScan#setAnalyzeImage(boolean)},
|
||||
* 因为{@link CameraScan#setAnalyzeImage(boolean)}方法能动态控制是否继续分析图像。
|
||||
*
|
||||
*/
|
||||
boolean onScanResultCallback(Result result);
|
||||
|
||||
@@ -170,6 +198,7 @@ public abstract class CameraScan implements ICamera,ICameraControl {
|
||||
|
||||
/**
|
||||
* 解析扫码结果
|
||||
*
|
||||
* @param data
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -29,6 +29,18 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.camera.view.PreviewView;
|
||||
|
||||
/**
|
||||
* 相机扫描基类;{@link CaptureActivity} 内部持有{@link CameraScan},便于快速实现扫描识别。
|
||||
* <p>
|
||||
* 快速实现扫描识别主要有以下几种方式:
|
||||
* <p>
|
||||
* 1、通过继承 {@link CaptureActivity}或者{@link CaptureFragment}或其子类,可快速实现扫描识别。
|
||||
* (适用于大多数场景,自定义布局时需覆写getLayoutId方法)
|
||||
* <p>
|
||||
* 2、在你项目的Activity或者Fragment中实例化一个{@link DefaultCameraScan}。(适用于想在扫码界面写交互逻辑,又因为项目
|
||||
* 架构或其它原因,无法直接或间接继承{@link CaptureActivity}或{@link CaptureFragment}时使用)
|
||||
* <p>
|
||||
* 3、继承{@link CameraScan}自己实现一个,可参照默认实现类{@link DefaultCameraScan},其他步骤同方式2。(高级用法,谨慎使用)
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureActivity extends AppCompatActivity implements CameraScan.OnScanResultCallback {
|
||||
@@ -85,7 +97,6 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
mCameraScan.setOnScanResultCallback(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 启动相机预览
|
||||
*/
|
||||
@@ -100,7 +111,6 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 释放相机
|
||||
*/
|
||||
@@ -133,6 +143,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* 请求Camera权限回调结果
|
||||
*
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
@@ -152,6 +163,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* 返回true时会自动初始化{@link #setContentView(int)},返回为false是需自己去初始化{@link #setContentView(int)}
|
||||
*
|
||||
* @return 默认返回true
|
||||
*/
|
||||
public boolean isContentView() {
|
||||
@@ -159,7 +171,8 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局id
|
||||
* 布局ID;通过覆写此方法可以自定义布局
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLayoutId() {
|
||||
@@ -168,6 +181,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* {@link #viewfinderView} 的 ID
|
||||
*
|
||||
* @return 默认返回{@code R.id.viewfinderView}, 如果不需要扫码框可以返回0
|
||||
*/
|
||||
public int getViewfinderViewId() {
|
||||
@@ -177,6 +191,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* 预览界面{@link #previewView} 的ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPreviewViewId() {
|
||||
@@ -185,6 +200,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* 获取 {@link #ivFlashlight} 的ID
|
||||
*
|
||||
* @return 默认返回{@code R.id.ivFlashlight}, 如果不需要手电筒按钮可以返回0
|
||||
*/
|
||||
public int getFlashlightId() {
|
||||
@@ -193,6 +209,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* Get {@link CameraScan}
|
||||
*
|
||||
* @return {@link #mCameraScan}
|
||||
*/
|
||||
public CameraScan getCameraScan() {
|
||||
@@ -201,6 +218,7 @@ public class CaptureActivity extends AppCompatActivity implements CameraScan.OnS
|
||||
|
||||
/**
|
||||
* 接收扫码结果回调
|
||||
*
|
||||
* @param result 扫码结果
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截,默认不拦截
|
||||
*/
|
||||
|
||||
@@ -30,6 +30,18 @@ import androidx.camera.view.PreviewView;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
/**
|
||||
* 相机扫描基类;{@link CaptureFragment} 内部持有{@link CameraScan},便于快速实现扫描识别。
|
||||
* <p>
|
||||
* 快速实现扫描识别主要有以下几种方式:
|
||||
* <p>
|
||||
* 1、通过继承 {@link CaptureActivity}或者{@link CaptureFragment}或其子类,可快速实现扫描识别。
|
||||
* (适用于大多数场景,自定义布局时需覆写getLayoutId方法)
|
||||
* <p>
|
||||
* 2、在你项目的Activity或者Fragment中实例化一个{@link DefaultCameraScan}。(适用于想在扫码界面写交互逻辑,又因为项目
|
||||
* 架构或其它原因,无法直接或间接继承{@link CaptureActivity}或{@link CaptureFragment}时使用)
|
||||
* <p>
|
||||
* 3、继承{@link CameraScan}自己实现一个,可参照默认实现类{@link DefaultCameraScan},其他步骤同方式2。(高级用法,谨慎使用)
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CaptureFragment extends Fragment implements CameraScan.OnScanResultCallback {
|
||||
@@ -53,7 +65,6 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
return fragment;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
if (isContentView()) {
|
||||
@@ -144,6 +155,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* 请求Camera权限回调结果
|
||||
*
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
*/
|
||||
@@ -163,6 +175,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* 返回true时会自动初始化{@link #createRootView(LayoutInflater, ViewGroup)},返回为false是需自己去初始化{@link #createRootView(LayoutInflater, ViewGroup)}
|
||||
*
|
||||
* @return 默认返回true
|
||||
*/
|
||||
public boolean isContentView() {
|
||||
@@ -171,6 +184,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* 创建{@link #mRootView}
|
||||
*
|
||||
* @param inflater
|
||||
* @param container
|
||||
* @return
|
||||
@@ -181,7 +195,8 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
}
|
||||
|
||||
/**
|
||||
* 布局id
|
||||
* 布局ID;通过覆写此方法可以自定义布局
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getLayoutId() {
|
||||
@@ -190,15 +205,16 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* {@link #viewfinderView} 的 ID
|
||||
*
|
||||
* @return 默认返回{@code R.id.viewfinderView}, 如果不需要扫码框可以返回0
|
||||
*/
|
||||
public int getViewfinderViewId() {
|
||||
return R.id.viewfinderView;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 预览界面{@link #previewView} 的ID
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getPreviewViewId() {
|
||||
@@ -207,6 +223,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* 获取 {@link #ivFlashlight} 的ID
|
||||
*
|
||||
* @return 默认返回{@code R.id.ivFlashlight}, 如果不需要手电筒按钮可以返回0
|
||||
*/
|
||||
public int getFlashlightId() {
|
||||
@@ -215,6 +232,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* Get {@link CameraScan}
|
||||
*
|
||||
* @return {@link #mCameraScan}
|
||||
*/
|
||||
public CameraScan getCameraScan() {
|
||||
@@ -223,6 +241,7 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
|
||||
/**
|
||||
* 接收扫码结果回调
|
||||
*
|
||||
* @param result 扫码结果
|
||||
* @return 返回true表示拦截,将不自动执行后续逻辑,为false表示不拦截,默认不拦截
|
||||
*/
|
||||
@@ -237,5 +256,4 @@ public class CaptureFragment extends Fragment implements CameraScan.OnScanResult
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,11 +12,12 @@ import java.util.Map;
|
||||
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
|
||||
/**
|
||||
* 解码配置:主要用于在扫码识别时,提供一些配置,便于扩展。通过配置可决定内置分析器的能力,从而间接的控制并简化扫码识别的流程
|
||||
* <p></>
|
||||
* 设置解码 {@link #setHints(Map)}内置的一些解码可参见如下:
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
* @see {@link DecodeFormatManager#DEFAULT_HINTS}
|
||||
* @see {@link DecodeFormatManager#ALL_HINTS}
|
||||
* @see {@link DecodeFormatManager#CODE_128_HINTS}
|
||||
@@ -24,7 +25,7 @@ import androidx.annotation.FloatRange;
|
||||
* @see {@link DecodeFormatManager#ONE_DIMENSIONAL_HINTS}
|
||||
* @see {@link DecodeFormatManager#TWO_DIMENSIONAL_HINTS}
|
||||
* @see {@link DecodeFormatManager#DEFAULT_HINTS}
|
||||
*
|
||||
* <p>
|
||||
* 如果不满足您也可以通过{@link DecodeFormatManager#createDecodeHints(BarcodeFormat...)}自己配置支持的格式
|
||||
*
|
||||
* <p></>
|
||||
@@ -32,14 +33,12 @@ import androidx.annotation.FloatRange;
|
||||
* {@link #setFullAreaScan(boolean)} 设置是否支持全区域扫码识别,优先级比识别区域高
|
||||
* {@link #setAnalyzeAreaRect(Rect)} 设置需要分析识别区域,优先级比识别区域比例高,当设置了指定的分析区域时,识别区域比例和识别区域偏移量相关参数都将无效
|
||||
* {@link #setAreaRectRatio(float)} 设置识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别,优先级最低
|
||||
*
|
||||
* <p>
|
||||
* 因为{@link androidx.camera.view.PreviewView}的预览区域是经过裁剪的,所以这里的区域并不是用户所能预览到的区域,而是指Camera预览的真实区域,
|
||||
* 您还可以通过{@link CameraScan#setCameraConfig(CameraConfig)}去自定义配置{@link CameraConfig}的配置信息控制预览相关配置信息
|
||||
*
|
||||
* <p>
|
||||
* 即判定区域分析的优先级顺序为:{@link #setFullAreaScan(boolean)} -> {@link #setAnalyzeAreaRect(Rect)} -> {@link #setAreaRectRatio(float)}
|
||||
* <p></>
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class DecodeConfig {
|
||||
|
||||
@@ -102,9 +101,11 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置解码
|
||||
* @param hints {@link DecodeFormatManager}
|
||||
*
|
||||
* @param hints {@link DecodeFormatManager}
|
||||
* <p>
|
||||
* 内置的一些解码可参见如下:
|
||||
* @return
|
||||
* @see {@link DecodeFormatManager#DEFAULT_HINTS}
|
||||
* @see {@link DecodeFormatManager#ALL_HINTS}
|
||||
* @see {@link DecodeFormatManager#CODE_128_HINTS}
|
||||
@@ -112,10 +113,8 @@ public class DecodeConfig {
|
||||
* @see {@link DecodeFormatManager#ONE_DIMENSIONAL_HINTS}
|
||||
* @see {@link DecodeFormatManager#TWO_DIMENSIONAL_HINTS}
|
||||
* @see {@link DecodeFormatManager#DEFAULT_HINTS}
|
||||
*
|
||||
* <p>
|
||||
* 如果不满足您也可以通过{@link DecodeFormatManager#createDecodeHints(BarcodeFormat...)}自己配置支持的格式
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DecodeConfig setHints(Map<DecodeHintType, Object> hints) {
|
||||
this.hints = hints;
|
||||
@@ -124,6 +123,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持识别反色码,黑白颜色反转
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSupportLuminanceInvert() {
|
||||
@@ -132,6 +132,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置是否支持识别反色码,黑白颜色反转
|
||||
*
|
||||
* @param supportLuminanceInvert 默认为{@code false},想要增强支持扫码识别反色码时可使用,相应的也会增加性能消耗。
|
||||
* @return
|
||||
*/
|
||||
@@ -142,6 +143,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持扫垂直的条码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSupportVerticalCode() {
|
||||
@@ -150,6 +152,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置是否支持扫垂直的条码
|
||||
*
|
||||
* @param supportVerticalCode 默认为{@code false},想要增强支持扫码识别垂直的条码时可使用,相应的也会增加性能消耗。
|
||||
* @return
|
||||
*/
|
||||
@@ -160,6 +163,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持使用多解码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isMultiDecode() {
|
||||
@@ -168,9 +172,10 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持使用多解码
|
||||
* @see {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
*
|
||||
* @param multiDecode 默认为{@code true}
|
||||
* @return
|
||||
* @see {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
*/
|
||||
public DecodeConfig setMultiDecode(boolean multiDecode) {
|
||||
isMultiDecode = multiDecode;
|
||||
@@ -179,6 +184,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持识别反色码(条码黑白颜色反转的码)使用多解码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSupportLuminanceInvertMultiDecode() {
|
||||
@@ -187,9 +193,10 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置是否支持识别反色码(条码黑白颜色反转的码)使用多解码
|
||||
* @see {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
*
|
||||
* @param supportLuminanceInvertMultiDecode 默认为{@code false},想要增强支持扫码识别反色码时可使用,相应的也会增加性能消耗。
|
||||
* @return
|
||||
* @see {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
*/
|
||||
public DecodeConfig setSupportLuminanceInvertMultiDecode(boolean supportLuminanceInvertMultiDecode) {
|
||||
isSupportLuminanceInvertMultiDecode = supportLuminanceInvertMultiDecode;
|
||||
@@ -198,6 +205,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持垂直的条码,使用多解码
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSupportVerticalCodeMultiDecode() {
|
||||
@@ -205,8 +213,8 @@ public class DecodeConfig {
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否支持垂直的条码,使用多解码
|
||||
* @see {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
* 设置是否支持垂直的条码,使用多解码;解码时,对应的二值化的实现: {@link HybridBinarizer} , {@link GlobalHistogramBinarizer}
|
||||
*
|
||||
* @param supportVerticalCodeMultiDecode 默认为{@code false},想要增强支持扫码识别垂直的条码时可使用,相应的也会增加性能消耗。
|
||||
* @return
|
||||
*/
|
||||
@@ -217,6 +225,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 需要分析识别区域
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Rect getAnalyzeAreaRect() {
|
||||
@@ -225,18 +234,16 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置需要分析识别区域,优先级比识别区域比例高,当设置了指定的分析区域时,识别区域比例和识别区域偏移量相关参数都将无效
|
||||
* @param analyzeAreaRect
|
||||
*
|
||||
* 识别区域可设置的方式有如下几种:
|
||||
* @param analyzeAreaRect 识别区域可设置的方式有如下几种:
|
||||
* {@link #setFullAreaScan(boolean)} 设置是否支持全区域扫码识别,优先级比识别区域高
|
||||
* {@link #setAnalyzeAreaRect(Rect)} 设置需要分析识别区域,优先级比识别区域比例高,当设置了指定的分析区域时,识别区域比例和识别区域偏移量相关参数都将无效
|
||||
* {@link #setAreaRectRatio(float)} 设置识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别,优先级最低
|
||||
*
|
||||
* <p>
|
||||
* 因为{@link androidx.camera.view.PreviewView}的预览区域是经过裁剪的,所以这里的区域并不是用户所能预览到的区域,而是指Camera预览的真实区域,
|
||||
* 您还可以通过{@link CameraScan#setCameraConfig(CameraConfig)}去自定义配置{@link CameraConfig}的配置信息控制预览相关配置信息
|
||||
*
|
||||
* <p>
|
||||
* 即判定区域分析的优先级顺序为:{@link #setFullAreaScan(boolean)} -> {@link #setAnalyzeAreaRect(Rect)} -> {@link #setAreaRectRatio(float)}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DecodeConfig setAnalyzeAreaRect(Rect analyzeAreaRect) {
|
||||
@@ -246,6 +253,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 是否支持全区域扫码识别
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isFullAreaScan() {
|
||||
@@ -254,16 +262,17 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置是否支持全区域扫码识别,优先级比识别区域高
|
||||
* @param fullAreaScan 默认为{@code true}
|
||||
*
|
||||
* @param fullAreaScan 默认为{@code true}
|
||||
* <p>
|
||||
* 识别区域可设置的方式有如下几种:
|
||||
* {@link #setFullAreaScan(boolean)} 设置是否支持全区域扫码识别,优先级比识别区域高
|
||||
* {@link #setAnalyzeAreaRect(Rect)} 设置需要分析识别区域,优先级比识别区域比例高,当设置了指定的分析区域时,识别区域比例和识别区域偏移量相关参数都将无效
|
||||
* {@link #setAreaRectRatio(float)} 设置识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别,优先级最低
|
||||
*
|
||||
* <p>
|
||||
* 因为{@link androidx.camera.view.PreviewView}的预览区域是经过裁剪的,所以这里的区域并不是用户所能预览到的区域,而是指Camera预览的真实区域,
|
||||
* 您还可以通过{@link CameraScan#setCameraConfig(CameraConfig)}去自定义配置{@link CameraConfig}的配置信息控制预览相关配置信息
|
||||
*
|
||||
* <p>
|
||||
* 即判定区域分析的优先级顺序为:{@link #setFullAreaScan(boolean)} -> {@link #setAnalyzeAreaRect(Rect)} -> {@link #setAreaRectRatio(float)}
|
||||
* @return
|
||||
*/
|
||||
@@ -274,6 +283,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public float getAreaRectRatio() {
|
||||
@@ -282,18 +292,16 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别,优先级最低
|
||||
* @param areaRectRatio
|
||||
*
|
||||
* 识别区域可设置的方式有如下几种:
|
||||
* @param areaRectRatio 识别区域可设置的方式有如下几种:
|
||||
* {@link #setFullAreaScan(boolean)} 设置是否支持全区域扫码识别,优先级比识别区域高
|
||||
* {@link #setAnalyzeAreaRect(Rect)} 设置需要分析识别区域,优先级比识别区域比例高,当设置了指定的分析区域时,识别区域比例和识别区域偏移量相关参数都将无效
|
||||
* {@link #setAreaRectRatio(float)} 设置识别区域比例,默认{@link #DEFAULT_AREA_RECT_RATIO},设置的比例最终会在预览区域裁剪基于此比例的一个矩形进行扫码识别,优先级最低
|
||||
*
|
||||
* <p>
|
||||
* 因为{@link androidx.camera.view.PreviewView}的预览区域是经过裁剪的,所以这里的区域并不是用户所能预览到的区域,而是指Camera预览的真实区域,
|
||||
* 您还可以通过{@link CameraScan#setCameraConfig(CameraConfig)}去自定义配置{@link CameraConfig}的配置信息控制预览相关配置信息
|
||||
*
|
||||
* <p>
|
||||
* 即判定区域分析的优先级顺序为:{@link #setFullAreaScan(boolean)} -> {@link #setAnalyzeAreaRect(Rect)} -> {@link #setAreaRectRatio(float)}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public DecodeConfig setAreaRectRatio(@FloatRange(from = 0.5, to = 1.0) float areaRectRatio) {
|
||||
@@ -303,6 +311,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 识别区域垂直方向偏移量,支持负数,大于0时,居中心向下偏移,小于0时,居中心向上偏移
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getAreaRectVerticalOffset() {
|
||||
@@ -311,6 +320,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置识别区域垂直方向偏移量,支持负数,大于0时,居中心向下偏移,小于0时,居中心向上偏移
|
||||
*
|
||||
* @param areaRectVerticalOffset
|
||||
* @return
|
||||
*/
|
||||
@@ -321,6 +331,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 识别区域水平方向偏移量,支持负数,大于0时,居中心向右偏移,小于0时,居中心向左偏移
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getAreaRectHorizontalOffset() {
|
||||
@@ -329,6 +340,7 @@ public class DecodeConfig {
|
||||
|
||||
/**
|
||||
* 设置识别区域水平方向偏移量,支持负数,大于0时,居中心向右偏移,小于0时,居中心向左偏移
|
||||
*
|
||||
* @param areaRectHorizontalOffset
|
||||
* @return
|
||||
*/
|
||||
|
||||
@@ -13,6 +13,10 @@ import java.util.Map;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* 解码格式管理器
|
||||
* <p>
|
||||
* 将常见的一些解码配置已根据条形码类型进行了几大划分,可根据需要找到符合的划分配置类型直接使用。
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class DecodeFormatManager {
|
||||
@@ -56,6 +60,7 @@ public final class DecodeFormatManager {
|
||||
|
||||
/**
|
||||
* 所有支持的{@link BarcodeFormat}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static List<BarcodeFormat> getAllFormats() {
|
||||
@@ -95,6 +100,7 @@ public final class DecodeFormatManager {
|
||||
* {@link BarcodeFormat#UPC_A}
|
||||
* {@link BarcodeFormat#UPC_E}
|
||||
* {@link BarcodeFormat#UPC_EAN_EXTENSION}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static List<BarcodeFormat> getOneDimensionalFormats() {
|
||||
@@ -122,6 +128,7 @@ public final class DecodeFormatManager {
|
||||
* {@link BarcodeFormat#MAXICODE}
|
||||
* {@link BarcodeFormat#PDF_417}
|
||||
* {@link BarcodeFormat#QR_CODE}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static List<BarcodeFormat> getTwoDimensionalFormats() {
|
||||
@@ -141,6 +148,7 @@ public final class DecodeFormatManager {
|
||||
* {@link BarcodeFormat#UPC_A}
|
||||
* {@link BarcodeFormat#EAN_13}
|
||||
* {@link BarcodeFormat#CODE_128}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static List<BarcodeFormat> getDefaultFormats() {
|
||||
@@ -152,12 +160,9 @@ public final class DecodeFormatManager {
|
||||
return list;
|
||||
}
|
||||
|
||||
private static <T> List<T> singletonList(T o){
|
||||
return Collections.singletonList(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* 支持解码的格式
|
||||
*
|
||||
* @param barcodeFormats {@link BarcodeFormat}
|
||||
* @return
|
||||
*/
|
||||
@@ -169,17 +174,17 @@ public final class DecodeFormatManager {
|
||||
|
||||
/**
|
||||
* 支持解码的格式
|
||||
*
|
||||
* @param barcodeFormat {@link BarcodeFormat}
|
||||
* @return
|
||||
*/
|
||||
public static Map<DecodeHintType, Object> createDecodeHint(@NonNull BarcodeFormat barcodeFormat) {
|
||||
Map<DecodeHintType, Object> hints = new EnumMap<>(DecodeHintType.class);
|
||||
addDecodeHintTypes(hints,singletonList(barcodeFormat));
|
||||
addDecodeHintTypes(hints, Collections.singletonList(barcodeFormat));
|
||||
return hints;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param hints
|
||||
* @param formats
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.king.zxing;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -27,6 +28,7 @@ import androidx.annotation.FloatRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.camera.core.Camera;
|
||||
import androidx.camera.core.CameraInfo;
|
||||
import androidx.camera.core.CameraSelector;
|
||||
import androidx.camera.core.FocusMeteringAction;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
@@ -43,6 +45,18 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
/**
|
||||
* 相机扫描基类;{@link DefaultCameraScan} 为 {@link CameraScan} 的默认实现
|
||||
* <p>
|
||||
* 快速实现扫描识别主要有以下几种方式:
|
||||
* <p>
|
||||
* 1、通过继承 {@link CaptureActivity}或者{@link CaptureFragment}或其子类,可快速实现扫描识别。
|
||||
* (适用于大多数场景,自定义布局时需覆写getLayoutId方法)
|
||||
* <p>
|
||||
* 2、在你项目的Activity或者Fragment中实例化一个{@link DefaultCameraScan}。(适用于想在扫码界面写交互逻辑,又因为项目
|
||||
* 架构或其它原因,无法直接或间接继承{@link CaptureActivity}或{@link CaptureFragment}时使用)
|
||||
* <p>
|
||||
* 3、继承{@link CameraScan}自己实现一个,可参照默认实现类{@link DefaultCameraScan},其他步骤同方式2。(高级用法,谨慎使用)
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class DefaultCameraScan extends CameraScan {
|
||||
@@ -61,6 +75,11 @@ public class DefaultCameraScan extends CameraScan {
|
||||
*/
|
||||
private static final int HOVER_TAP_SLOP = 20;
|
||||
|
||||
/**
|
||||
* 每次缩放改变的步长
|
||||
*/
|
||||
private static final float ZOOM_STEP_SIZE = 0.1F;
|
||||
|
||||
private FragmentActivity mFragmentActivity;
|
||||
private Context mContext;
|
||||
private LifecycleOwner mLifecycleOwner;
|
||||
@@ -92,8 +111,8 @@ public class DefaultCameraScan extends CameraScan {
|
||||
private AmbientLightManager mAmbientLightManager;
|
||||
|
||||
private int mOrientation;
|
||||
private int mScreenWidth;
|
||||
private int mScreenHeight;
|
||||
private int mImageWidth;
|
||||
private int mImageHeight;
|
||||
private long mLastAutoZoomTime;
|
||||
private long mLastHoveTapTime;
|
||||
private boolean isClickTap;
|
||||
@@ -116,19 +135,28 @@ public class DefaultCameraScan extends CameraScan {
|
||||
initData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 缩放手势检测
|
||||
*/
|
||||
private ScaleGestureDetector.OnScaleGestureListener mOnScaleGestureListener = new ScaleGestureDetector.SimpleOnScaleGestureListener() {
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = detector.getScaleFactor();
|
||||
if (mCamera != null) {
|
||||
float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio();
|
||||
// 根据缩放的手势和当前比例进行缩放
|
||||
zoomTo(ratio * scale);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void initData() {
|
||||
mResultLiveData = new MutableLiveData<>();
|
||||
mResultLiveData.observe(mLifecycleOwner, result -> {
|
||||
@@ -150,15 +178,8 @@ public class DefaultCameraScan extends CameraScan {
|
||||
return false;
|
||||
});
|
||||
|
||||
DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
|
||||
mScreenWidth = displayMetrics.widthPixels;
|
||||
mScreenHeight = displayMetrics.heightPixels;
|
||||
|
||||
LogUtils.d(String.format("displayMetrics:%dx%d",mScreenWidth,mScreenHeight));
|
||||
|
||||
mBeepManager = new BeepManager(mContext);
|
||||
mAmbientLightManager = new AmbientLightManager(mContext);
|
||||
if(mAmbientLightManager != null){
|
||||
mAmbientLightManager.register();
|
||||
mAmbientLightManager.setOnLightSensorEventListener((dark, lightLux) -> {
|
||||
if (flashlightView != null) {
|
||||
@@ -171,12 +192,15 @@ public class DefaultCameraScan extends CameraScan {
|
||||
flashlightView.setVisibility(View.INVISIBLE);
|
||||
flashlightView.setSelected(false);
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理预览视图点击事件;如果触发的点击事件被判定对焦操作,则开始自动对焦
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
private void handlePreviewViewClickTap(MotionEvent event) {
|
||||
if (event.getPointerCount() == 1) {
|
||||
switch (event.getAction()) {
|
||||
@@ -191,6 +215,7 @@ public class DefaultCameraScan extends CameraScan {
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
if (isClickTap && mLastHoveTapTime + HOVER_TAP_TIMEOUT > System.currentTimeMillis()) {
|
||||
// 开始对焦和测光
|
||||
startFocusAndMetering(event.getX(), event.getY());
|
||||
}
|
||||
break;
|
||||
@@ -198,6 +223,12 @@ public class DefaultCameraScan extends CameraScan {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始对焦和测光
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
private void startFocusAndMetering(float x, float y) {
|
||||
if (mCamera != null) {
|
||||
MeteringPoint point = mPreviewView.getMeteringPointFactory().createPoint(x, y);
|
||||
@@ -209,8 +240,9 @@ public class DefaultCameraScan extends CameraScan {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 初始化配置
|
||||
*/
|
||||
private void initConfig() {
|
||||
if (mCameraConfig == null) {
|
||||
mCameraConfig = new CameraConfig();
|
||||
@@ -248,6 +280,8 @@ public class DefaultCameraScan extends CameraScan {
|
||||
.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
|
||||
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST));
|
||||
imageAnalysis.setAnalyzer(Executors.newSingleThreadExecutor(), image -> {
|
||||
mImageWidth = image.getWidth();
|
||||
mImageHeight = image.getHeight();
|
||||
if (isAnalyze && !isAnalyzeResult && mAnalyzer != null) {
|
||||
Result result = mAnalyzer.analyze(image, mOrientation);
|
||||
mResultLiveData.postValue(result);
|
||||
@@ -268,6 +302,7 @@ public class DefaultCameraScan extends CameraScan {
|
||||
|
||||
/**
|
||||
* 处理分析结果
|
||||
*
|
||||
* @param result
|
||||
*/
|
||||
private synchronized void handleAnalyzeResult(Result result) {
|
||||
@@ -299,8 +334,14 @@ public class DefaultCameraScan extends CameraScan {
|
||||
scanResultCallback(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理自动缩放
|
||||
* @param distance
|
||||
* @param result
|
||||
* @return
|
||||
*/
|
||||
private boolean handleAutoZoom(int distance, Result result) {
|
||||
int size = Math.min(mScreenWidth,mScreenHeight);
|
||||
int size = Math.min(mImageWidth, mImageHeight);
|
||||
if (distance * 4 < size) {
|
||||
mLastAutoZoomTime = System.currentTimeMillis();
|
||||
zoomIn();
|
||||
@@ -310,6 +351,10 @@ public class DefaultCameraScan extends CameraScan {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描结果回调
|
||||
* @param result
|
||||
*/
|
||||
private void scanResultCallback(Result result) {
|
||||
if (mOnScanResultCallback != null && mOnScanResultCallback.onScanResultCallback(result)) {
|
||||
/*
|
||||
@@ -329,7 +374,6 @@ public class DefaultCameraScan extends CameraScan {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void stopCamera() {
|
||||
if (mCameraProviderFuture != null) {
|
||||
@@ -353,11 +397,12 @@ public class DefaultCameraScan extends CameraScan {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void zoomIn() {
|
||||
if (mCamera != null) {
|
||||
float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio() + 0.1f;
|
||||
float maxRatio = mCamera.getCameraInfo().getZoomState().getValue().getMaxZoomRatio();
|
||||
float ratio = getCameraInfo().getZoomState().getValue().getZoomRatio() + ZOOM_STEP_SIZE;
|
||||
float maxRatio = getCameraInfo().getZoomState().getValue().getMaxZoomRatio();
|
||||
if (ratio <= maxRatio) {
|
||||
mCamera.getCameraControl().setZoomRatio(ratio);
|
||||
}
|
||||
@@ -367,19 +412,18 @@ public class DefaultCameraScan extends CameraScan {
|
||||
@Override
|
||||
public void zoomOut() {
|
||||
if (mCamera != null) {
|
||||
float ratio = mCamera.getCameraInfo().getZoomState().getValue().getZoomRatio() - 0.1f;
|
||||
float minRatio = mCamera.getCameraInfo().getZoomState().getValue().getMinZoomRatio();
|
||||
float ratio = getCameraInfo().getZoomState().getValue().getZoomRatio() - ZOOM_STEP_SIZE;
|
||||
float minRatio = getCameraInfo().getZoomState().getValue().getMinZoomRatio();
|
||||
if (ratio >= minRatio) {
|
||||
mCamera.getCameraControl().setZoomRatio(ratio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void zoomTo(float ratio) {
|
||||
if (mCamera != null) {
|
||||
ZoomState zoomState = mCamera.getCameraInfo().getZoomState().getValue();
|
||||
ZoomState zoomState = getCameraInfo().getZoomState().getValue();
|
||||
float maxRatio = zoomState.getMaxZoomRatio();
|
||||
float minRatio = zoomState.getMinZoomRatio();
|
||||
float zoom = Math.max(Math.min(ratio, maxRatio), minRatio);
|
||||
@@ -390,7 +434,7 @@ public class DefaultCameraScan extends CameraScan {
|
||||
@Override
|
||||
public void lineZoomIn() {
|
||||
if (mCamera != null) {
|
||||
float zoom = mCamera.getCameraInfo().getZoomState().getValue().getLinearZoom() + 0.1f;
|
||||
float zoom = getCameraInfo().getZoomState().getValue().getLinearZoom() + ZOOM_STEP_SIZE;
|
||||
if (zoom <= 1f) {
|
||||
mCamera.getCameraControl().setLinearZoom(zoom);
|
||||
}
|
||||
@@ -400,7 +444,7 @@ public class DefaultCameraScan extends CameraScan {
|
||||
@Override
|
||||
public void lineZoomOut() {
|
||||
if (mCamera != null) {
|
||||
float zoom = mCamera.getCameraInfo().getZoomState().getValue().getLinearZoom() - 0.1f;
|
||||
float zoom = getCameraInfo().getZoomState().getValue().getLinearZoom() - ZOOM_STEP_SIZE;
|
||||
if (zoom >= 0f) {
|
||||
mCamera.getCameraControl().setLinearZoom(zoom);
|
||||
}
|
||||
@@ -431,6 +475,7 @@ public class DefaultCameraScan extends CameraScan {
|
||||
|
||||
/**
|
||||
* 是否支持闪光灯
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@@ -469,6 +514,14 @@ public class DefaultCameraScan extends CameraScan {
|
||||
return mCamera;
|
||||
}
|
||||
|
||||
/**
|
||||
* CameraInfo
|
||||
*
|
||||
* @return {@link CameraInfo}
|
||||
*/
|
||||
private CameraInfo getCameraInfo() {
|
||||
return mCamera.getCameraInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void release() {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package com.king.zxing;
|
||||
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.camera.core.Camera;
|
||||
|
||||
/**
|
||||
* 相机定义
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface ICamera {
|
||||
@@ -21,9 +22,11 @@ public interface ICamera {
|
||||
|
||||
/**
|
||||
* 获取{@link Camera}
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@Nullable Camera getCamera();
|
||||
@Nullable
|
||||
Camera getCamera();
|
||||
|
||||
/**
|
||||
* 释放
|
||||
|
||||
@@ -3,6 +3,8 @@ package com.king.zxing;
|
||||
import androidx.annotation.FloatRange;
|
||||
|
||||
/**
|
||||
* 相机控制:主要包括调节焦距和闪光灯控制
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface ICameraControl {
|
||||
@@ -19,6 +21,7 @@ public interface ICameraControl {
|
||||
|
||||
/**
|
||||
* 缩放到指定比例
|
||||
*
|
||||
* @param ratio
|
||||
*/
|
||||
void zoomTo(float ratio);
|
||||
@@ -35,24 +38,28 @@ public interface ICameraControl {
|
||||
|
||||
/**
|
||||
* 线性缩放到指定比例
|
||||
*
|
||||
* @param linearZoom
|
||||
*/
|
||||
void lineZoomTo(@FloatRange(from = 0.0, to = 1.0) float linearZoom);
|
||||
|
||||
/**
|
||||
* 设置闪光灯(手电筒)是否开启
|
||||
*
|
||||
* @param torch
|
||||
*/
|
||||
void enableTorch(boolean torch);
|
||||
|
||||
/**
|
||||
* 闪光灯(手电筒)是否开启
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean isTorchEnabled();
|
||||
|
||||
/**
|
||||
* 是否支持闪光灯
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean hasFlashUnit();
|
||||
|
||||
@@ -1,30 +1,20 @@
|
||||
package com.king.zxing;
|
||||
/*
|
||||
* Copyright (C) 2008 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.Layout;
|
||||
import android.text.StaticLayout;
|
||||
import android.text.TextPaint;
|
||||
@@ -32,28 +22,37 @@ import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.TypedValue;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.ColorInt;
|
||||
import androidx.annotation.ColorRes;
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import static com.king.zxing.ViewfinderView.FrameGravity.*;
|
||||
|
||||
/**
|
||||
* This view is overlaid on top of the camera preview. It adds the viewfinder rectangle and partial
|
||||
* transparency outside it, as well as the laser scanner animation and result points.
|
||||
* 取景视图:主要用于渲染扫描效果
|
||||
*
|
||||
* @author dswitkin@google.com (Daniel Switkin)
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class ViewfinderView extends View {
|
||||
|
||||
private static final int CURRENT_POINT_OPACITY = 0xA0;
|
||||
private static final int MAX_RESULT_POINTS = 20;
|
||||
private static final int POINT_SIZE = 30;
|
||||
/**
|
||||
* 默认范围比例,之所以默认为 1.2 是因为内切圆半径和外切圆半径之和的二分之一(即:(1 + √2) / 2 ≈ 1.2)
|
||||
*/
|
||||
private final float DEFAULT_RANGE_RATIO = 1.2F;
|
||||
|
||||
private final float MAX_ZOOM_RATIO = 1.2F;
|
||||
|
||||
/**
|
||||
* 画笔
|
||||
@@ -186,18 +185,71 @@ public class ViewfinderView extends View {
|
||||
*/
|
||||
private FrameGravity frameGravity;
|
||||
|
||||
|
||||
private Point point;
|
||||
private int pointColor;
|
||||
private int pointStrokeColor;
|
||||
private Bitmap pointBitmap;
|
||||
private boolean isShowPointAnim = true;
|
||||
|
||||
private float pointRadius;
|
||||
private float pointStrokeRatio = 1.2f;
|
||||
private float pointStrokeRatio;
|
||||
private float pointStrokeRadius;
|
||||
|
||||
/**
|
||||
* 当前缩放比例
|
||||
*/
|
||||
private float currentZoomRatio = 1.0f;
|
||||
/**
|
||||
* 最后一次缩放比例(即上一次缩放比例)
|
||||
*/
|
||||
private float lastZoomRatio;
|
||||
/**
|
||||
* 缩放速度
|
||||
*/
|
||||
private float zoomSpeed = 0.02f;
|
||||
|
||||
private int zoomCount;
|
||||
|
||||
/**
|
||||
* 结果点有效点击范围半径
|
||||
*/
|
||||
private float pointRangeRadius;
|
||||
|
||||
private Bitmap laserBitmap;
|
||||
|
||||
private int viewfinderStyle = ViewfinderStyle.CLASSIC;
|
||||
|
||||
private List<Point> pointList;
|
||||
|
||||
private boolean isShowPoints = false;
|
||||
|
||||
private OnItemClickListener onItemClickListener;
|
||||
|
||||
private GestureDetector gestureDetector;
|
||||
|
||||
/**
|
||||
* 取景框样式
|
||||
*/
|
||||
@IntDef({ViewfinderStyle.CLASSIC, ViewfinderStyle.POPULAR})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ViewfinderStyle {
|
||||
/**
|
||||
* 经典样式:经典的扫码风格(带扫码框)
|
||||
*/
|
||||
int CLASSIC = 0;
|
||||
/**
|
||||
* 流行样式:类似于新版的微信全屏扫码(不带扫码框)
|
||||
*/
|
||||
int POPULAR = 1;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描线样式
|
||||
*/
|
||||
public enum LaserStyle {
|
||||
NONE(0),LINE(1),GRID(2);
|
||||
NONE(0), LINE(1), GRID(2), IMAGE(3);
|
||||
private int mValue;
|
||||
|
||||
LaserStyle(int value) {
|
||||
mValue = value;
|
||||
}
|
||||
@@ -212,6 +264,9 @@ public class ViewfinderView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文字位置
|
||||
*/
|
||||
public enum TextLocation {
|
||||
TOP(0), BOTTOM(1);
|
||||
|
||||
@@ -231,7 +286,9 @@ public class ViewfinderView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 扫码框对齐方式
|
||||
*/
|
||||
public enum FrameGravity {
|
||||
CENTER(0), LEFT(1), TOP(2), RIGHT(3), BOTTOM(4);
|
||||
|
||||
@@ -264,7 +321,12 @@ public class ViewfinderView extends View {
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @param context
|
||||
* @param attrs
|
||||
*/
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
// 初始化自定义属性信息
|
||||
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ViewfinderView);
|
||||
@@ -298,16 +360,53 @@ public class ViewfinderView extends View {
|
||||
framePaddingTop = array.getDimension(R.styleable.ViewfinderView_framePaddingTop, 0);
|
||||
framePaddingRight = array.getDimension(R.styleable.ViewfinderView_framePaddingRight, 0);
|
||||
framePaddingBottom = array.getDimension(R.styleable.ViewfinderView_framePaddingBottom, 0);
|
||||
frameGravity = FrameGravity.getFromInt(array.getInt(R.styleable.ViewfinderView_frameGravity, CENTER.mValue));
|
||||
frameGravity = FrameGravity.getFromInt(array.getInt(R.styleable.ViewfinderView_frameGravity, FrameGravity.CENTER.mValue));
|
||||
|
||||
pointColor = array.getColor(R.styleable.ViewfinderView_pointColor, ContextCompat.getColor(context, R.color.viewfinder_point));
|
||||
pointStrokeColor = array.getColor(R.styleable.ViewfinderView_pointStrokeColor, Color.WHITE);
|
||||
pointRadius = array.getDimension(R.styleable.ViewfinderView_pointRadius, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, getResources().getDisplayMetrics()));
|
||||
pointStrokeRatio = array.getFloat(R.styleable.ViewfinderView_pointStrokeRatio, DEFAULT_RANGE_RATIO);
|
||||
isShowPointAnim = array.getBoolean(R.styleable.ViewfinderView_showPointAnim, true);
|
||||
Drawable pointDrawable = array.getDrawable(R.styleable.ViewfinderView_pointDrawable);
|
||||
Drawable laserDrawable = array.getDrawable(R.styleable.ViewfinderView_laserDrawable);
|
||||
viewfinderStyle = array.getInt(R.styleable.ViewfinderView_viewfinderStyle, ViewfinderStyle.CLASSIC);
|
||||
|
||||
array.recycle();
|
||||
|
||||
pointColor = laserColor;
|
||||
pointStrokeColor = Color.WHITE;
|
||||
if (pointDrawable != null) {
|
||||
pointBitmap = getBitmapFormDrawable(pointDrawable);
|
||||
pointRangeRadius = (pointBitmap.getWidth() + pointBitmap.getHeight()) / 4 * DEFAULT_RANGE_RATIO;
|
||||
} else {
|
||||
pointStrokeRadius = pointRadius * pointStrokeRatio;
|
||||
pointRangeRadius = pointStrokeRadius * DEFAULT_RANGE_RATIO;
|
||||
}
|
||||
|
||||
if (laserDrawable != null) {
|
||||
laserBitmap = getBitmapFormDrawable(laserDrawable);
|
||||
}
|
||||
|
||||
pointRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics());
|
||||
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setAntiAlias(true);
|
||||
textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
|
||||
@Override
|
||||
public boolean onSingleTapUp(MotionEvent e) {
|
||||
if (isShowPoints && checkSingleTap(e.getX(), e.getY())) {
|
||||
return true;
|
||||
}
|
||||
return super.onSingleTapUp(e);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private Bitmap getBitmapFormDrawable(@NonNull Drawable drawable) {
|
||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
drawable.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private DisplayMetrics getDisplayMetrics() {
|
||||
@@ -330,21 +429,25 @@ public class ViewfinderView extends View {
|
||||
this.labelTextSize = textSize;
|
||||
}
|
||||
|
||||
public void setLaserStyle(LaserStyle laserStyle) {
|
||||
this.laserStyle = laserStyle;
|
||||
}
|
||||
|
||||
public void setPointImageResource(@DrawableRes int drawable) {
|
||||
setPointBitmap(BitmapFactory.decodeResource(getResources(), drawable));
|
||||
}
|
||||
|
||||
public void setPointBitmap(Bitmap bitmap) {
|
||||
pointBitmap = bitmap;
|
||||
pointRangeRadius = (pointBitmap.getWidth() + pointBitmap.getHeight()) / 4 * DEFAULT_RANGE_RATIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
LogUtils.d("onLayout" + getWidth() + "," + getHeight());
|
||||
initFrame(getWidth(),getHeight());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
LogUtils.d("onSizeChanged" + w + "," + h);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void initFrame(int width, int height) {
|
||||
|
||||
int size = (int) (Math.min(width, height) * frameRatio);
|
||||
@@ -384,6 +487,17 @@ public class ViewfinderView extends View {
|
||||
@Override
|
||||
public void onDraw(Canvas canvas) {
|
||||
|
||||
if (isShowPoints) {
|
||||
// 显示结果点
|
||||
drawMask(canvas, getWidth(), getHeight());
|
||||
drawResultPoints(canvas, pointList);
|
||||
if (isShowPointAnim && pointBitmap == null) {
|
||||
// 显示动画并且结果点标记的图片为空时,支持缩放动画
|
||||
calcZoomPointAnim();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (frame == null) {
|
||||
return;
|
||||
}
|
||||
@@ -393,11 +507,9 @@ public class ViewfinderView extends View {
|
||||
scannerEnd = frame.bottom - scannerLineHeight;
|
||||
}
|
||||
|
||||
int width = canvas.getWidth();
|
||||
int height = canvas.getHeight();
|
||||
|
||||
if (viewfinderStyle == ViewfinderStyle.CLASSIC) {// CLASSIC样式:经典样式(带扫码框)
|
||||
// 绘制模糊区域
|
||||
drawExterior(canvas,frame,width,height);
|
||||
drawExterior(canvas, frame, getWidth(), getHeight());
|
||||
// 绘制扫描动画
|
||||
drawLaserScanner(canvas, frame);
|
||||
// 绘制取景区域框
|
||||
@@ -408,10 +520,17 @@ public class ViewfinderView extends View {
|
||||
drawTextInfo(canvas, frame);
|
||||
// 间隔更新取景区域
|
||||
postInvalidateDelayed(scannerAnimationDelay, frame.left, frame.top, frame.right, frame.bottom);
|
||||
} else if (viewfinderStyle == ViewfinderStyle.POPULAR) {// POPULAR样式:类似于新版的微信全屏扫码(不带扫码框)
|
||||
// 绘制扫描动画
|
||||
drawLaserScanner(canvas, frame);
|
||||
postInvalidateDelayed(scannerAnimationDelay);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制文本
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -420,6 +539,7 @@ public class ViewfinderView extends View {
|
||||
textPaint.setColor(labelTextColor);
|
||||
textPaint.setTextSize(labelTextSize);
|
||||
textPaint.setTextAlign(Paint.Align.CENTER);
|
||||
|
||||
StaticLayout staticLayout = new StaticLayout(labelText, textPaint, labelTextWidth, Layout.Alignment.ALIGN_NORMAL, 1.2f, 0.0f, true);
|
||||
if (labelTextLocation == TextLocation.BOTTOM) {
|
||||
canvas.translate(frame.left + frame.width() / 2, frame.bottom + labelTextPadding);
|
||||
@@ -433,6 +553,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 绘制边角
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -452,8 +573,30 @@ public class ViewfinderView extends View {
|
||||
canvas.drawRect(frame.right - cornerRectHeight, frame.bottom - cornerRectWidth, frame.right, frame.bottom, paint);
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制扫码动画
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
private void drawImageScanner(Canvas canvas, Rect frame) {
|
||||
if (laserBitmap != null) {
|
||||
paint.setColor(Color.WHITE);
|
||||
canvas.drawBitmap(laserBitmap, frame.left, scannerStart, paint);
|
||||
if (scannerStart < scannerEnd) {
|
||||
scannerStart += scannerLineMoveDistance;
|
||||
} else {
|
||||
scannerStart = frame.top;
|
||||
}
|
||||
} else {
|
||||
drawLineScanner(canvas, frame);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制激光扫描线
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -467,6 +610,9 @@ public class ViewfinderView extends View {
|
||||
case GRID:// 网格
|
||||
drawGridScanner(canvas, frame);
|
||||
break;
|
||||
case IMAGE:// 图片
|
||||
drawImageScanner(canvas, frame);
|
||||
break;
|
||||
}
|
||||
paint.setShader(null);
|
||||
}
|
||||
@@ -474,6 +620,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 绘制线性式扫描
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -487,7 +634,7 @@ public class ViewfinderView extends View {
|
||||
Shader.TileMode.MIRROR);
|
||||
|
||||
paint.setShader(linearGradient);
|
||||
if(scannerStart <= scannerEnd) {
|
||||
if (scannerStart < scannerEnd) {
|
||||
// 椭圆
|
||||
RectF rectF = new RectF(frame.left + 2 * scannerLineHeight, scannerStart, frame.right - 2 * scannerLineHeight, scannerStart + scannerLineHeight);
|
||||
canvas.drawOval(rectF, paint);
|
||||
@@ -499,6 +646,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 绘制网格式扫描
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -536,6 +684,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 处理颜色模糊
|
||||
*
|
||||
* @param color
|
||||
* @return
|
||||
*/
|
||||
@@ -547,6 +696,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 绘制扫描区边框
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
*/
|
||||
@@ -560,6 +710,7 @@ public class ViewfinderView extends View {
|
||||
|
||||
/**
|
||||
* 绘制模糊区域
|
||||
*
|
||||
* @param canvas
|
||||
* @param frame
|
||||
* @param width
|
||||
@@ -575,16 +726,173 @@ public class ViewfinderView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制遮罩层
|
||||
*
|
||||
* @param canvas
|
||||
* @param width
|
||||
* @param height
|
||||
*/
|
||||
private void drawMask(Canvas canvas, int width, int height) {
|
||||
if (maskColor != 0) {
|
||||
paint.setColor(maskColor);
|
||||
canvas.drawRect(0, 0, width, height, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public void drawViewfinder() {
|
||||
/**
|
||||
* 根据结果点集合绘制结果点
|
||||
*
|
||||
* @param canvas
|
||||
* @param points
|
||||
*/
|
||||
private void drawResultPoints(Canvas canvas, List<Point> points) {
|
||||
paint.setColor(Color.WHITE);
|
||||
if (points != null) {
|
||||
for (Point point : points) {
|
||||
drawResultPoint(canvas, point, currentZoomRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算点的缩放动画
|
||||
*/
|
||||
private void calcZoomPointAnim() {
|
||||
if (currentZoomRatio <= 1F) {
|
||||
lastZoomRatio = currentZoomRatio;
|
||||
currentZoomRatio += zoomSpeed;
|
||||
|
||||
if (zoomCount < 2) {
|
||||
// 记住缩放回合次数
|
||||
zoomCount++;
|
||||
} else {
|
||||
zoomCount = 0;
|
||||
}
|
||||
} else if (currentZoomRatio >= MAX_ZOOM_RATIO) {
|
||||
lastZoomRatio = currentZoomRatio;
|
||||
currentZoomRatio -= zoomSpeed;
|
||||
} else {
|
||||
if (lastZoomRatio > currentZoomRatio) {
|
||||
lastZoomRatio = currentZoomRatio;
|
||||
currentZoomRatio -= zoomSpeed;
|
||||
} else {
|
||||
lastZoomRatio = currentZoomRatio;
|
||||
currentZoomRatio += zoomSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
// 每间隔3秒触发一套缩放动画,一套动画缩放三个回合(即:每次zoomCount累加到2后重置为0时)
|
||||
postInvalidateDelayed(zoomCount == 0 && lastZoomRatio == 1f ? 3000 : scannerAnimationDelay * 2);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 绘制结果点
|
||||
*
|
||||
* @param canvas
|
||||
* @param point
|
||||
*/
|
||||
private void drawResultPoint(Canvas canvas, Point point, float currentZoomRatio) {
|
||||
if (pointBitmap != null) {
|
||||
float left = point.x - pointBitmap.getWidth() / 2.0f;
|
||||
float top = point.y - pointBitmap.getHeight() / 2.0f;
|
||||
canvas.drawBitmap(pointBitmap, left, top, paint);
|
||||
} else {
|
||||
paint.setColor(pointStrokeColor);
|
||||
canvas.drawCircle(point.x, point.y, pointStrokeRadius * currentZoomRatio, paint);
|
||||
|
||||
paint.setColor(pointColor);
|
||||
canvas.drawCircle(point.x, point.y, pointRadius * currentZoomRatio, paint);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
if (isShowPoints) {
|
||||
gestureDetector.onTouchEvent(event);
|
||||
}
|
||||
return isShowPoints || super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
private boolean checkSingleTap(float x, float y) {
|
||||
if (pointList != null) {
|
||||
for (int i = 0; i < pointList.size(); i++) {
|
||||
Point point = pointList.get(i);
|
||||
float distance = getDistance(x, y, point.x, point.y);
|
||||
if (distance <= pointRangeRadius) {
|
||||
if (onItemClickListener != null) {
|
||||
onItemClickListener.onItemClick(i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取两点之间的距离
|
||||
*
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @return
|
||||
*/
|
||||
private float getDistance(float x1, float y1, float x2, float y2) {
|
||||
return (float) Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否显示结果点
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isShowPoints() {
|
||||
return isShowPoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示扫码动画
|
||||
*/
|
||||
public void showScanner() {
|
||||
isShowPoints = false;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public void setLaserStyle(LaserStyle laserStyle) {
|
||||
this.laserStyle = laserStyle;
|
||||
/**
|
||||
* 显示结果点
|
||||
*
|
||||
* @param points
|
||||
*/
|
||||
public void showResultPoints(List<Point> points) {
|
||||
pointList = points;
|
||||
isShowPoints = true;
|
||||
zoomCount = 0;
|
||||
lastZoomRatio = 0;
|
||||
currentZoomRatio = 1;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置点击Item监听
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void setOnItemClickListener(OnItemClickListener listener) {
|
||||
onItemClickListener = listener;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Item点击监听
|
||||
*/
|
||||
public interface OnItemClickListener {
|
||||
void onItemClick(int position);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.king.zxing.analyze;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import com.google.zxing.Result;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.camera.core.ImageProxy;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
/**
|
||||
* 分析器
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public interface Analyzer {
|
||||
|
||||
/**
|
||||
* Analyzes an image to produce a result.
|
||||
*
|
||||
* @param image The image to analyze
|
||||
* @param orientation {@link Configuration#ORIENTATION_LANDSCAPE}, {@link Configuration#ORIENTATION_PORTRAIT}.
|
||||
* @return
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.util.Map;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 矩阵区域分析器:主要用于锁定具体的识别区域
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public abstract class AreaRectAnalyzer extends ImageAnalyzer {
|
||||
|
||||
@@ -11,12 +11,13 @@ import com.google.zxing.common.HybridBinarizer;
|
||||
import com.king.zxing.DecodeConfig;
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* 多格式分析器:主要用于分析识别条形码/二维码
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class MultiFormatAnalyzer extends AreaRectAnalyzer {
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.king.zxing.config;
|
||||
import android.content.Context;
|
||||
import android.util.DisplayMetrics;
|
||||
|
||||
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
@@ -13,7 +12,8 @@ import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.Preview;
|
||||
|
||||
/**
|
||||
* 相机配置:根据纵横比配置相机,使输出分析的图像尽可能的接近屏幕比例
|
||||
* 相机配置:根据纵横比配置相机,使输出分析的图像尽可能的接近屏幕的比例
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class AspectRatioCameraConfig extends CameraConfig {
|
||||
@@ -22,22 +22,26 @@ public final class AspectRatioCameraConfig extends CameraConfig {
|
||||
|
||||
public AspectRatioCameraConfig(Context context) {
|
||||
super();
|
||||
initTargetAspectRatio(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 {@link #mAspectRatio}
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void initTargetAspectRatio(Context context) {
|
||||
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
|
||||
int width = displayMetrics.widthPixels;
|
||||
int height = displayMetrics.heightPixels;
|
||||
|
||||
mAspectRatio = aspectRatio(width, height);
|
||||
LogUtils.d("aspectRatio:" + mAspectRatio);
|
||||
|
||||
}
|
||||
|
||||
private int aspectRatio(float width, float height){
|
||||
float ratio = Math.max(width, height) / Math.min(width, height);
|
||||
if (Math.abs(ratio - 4.0f / 3.0f) < Math.abs(ratio - 16.0f / 9.0f)) {
|
||||
return AspectRatio.RATIO_4_3;
|
||||
if (Math.abs(ratio - 4.0F / 3.0F) < Math.abs(ratio - 16.0F / 9.0F)) {
|
||||
mAspectRatio = AspectRatio.RATIO_4_3;
|
||||
} else {
|
||||
mAspectRatio = AspectRatio.RATIO_16_9;
|
||||
}
|
||||
return AspectRatio.RATIO_16_9;
|
||||
LogUtils.d("aspectRatio:" + mAspectRatio);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -59,3 +63,4 @@ public final class AspectRatioCameraConfig extends CameraConfig {
|
||||
return super.options(builder);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,23 @@ import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.Preview;
|
||||
|
||||
/**
|
||||
* 相机配置:主要用于提供相机预览时可自定义一些配置,便于扩展
|
||||
* 相机配置:主要用于提供相机预览时可自定义一些配置,便于拓展;
|
||||
* <p>
|
||||
* 库中内置实现{@link CameraConfig}的有{@link AspectRatioCameraConfig}和{@link ResolutionCameraConfig};
|
||||
* <p>
|
||||
* 这里简单说下各自的特点:
|
||||
* <p>
|
||||
* {@link CameraConfig} - 默认的相机配置
|
||||
* <p>
|
||||
* {@link AspectRatioCameraConfig} - 根据纵横比配置相机,使输出分析的图像尽可能的接近屏幕的比例
|
||||
* <p>
|
||||
* {@link ResolutionCameraConfig} - 根据尺寸配置相机的目标图像大小,使输出分析的图像的分辨率尽可能的接近屏幕尺寸
|
||||
* <p>
|
||||
* 当使用默认的 {@link CameraConfig}在某些机型上体验欠佳时,你可以尝试使用{@link AspectRatioCameraConfig}或
|
||||
* {@link ResolutionCameraConfig}会有意想不到奇效。
|
||||
* <p>
|
||||
* 你也可以自定义或覆写 {@link CameraConfig} 中的 {@link #options} 方法,根据需要定制配置。
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class CameraConfig {
|
||||
@@ -15,19 +31,50 @@ public class CameraConfig {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置 {@link Preview.Builder};可参考:{@link AspectRatioCameraConfig} 或 {@link ResolutionCameraConfig}
|
||||
* <p>
|
||||
* 如配置目标旋转角度为90度:{@code builder.setTargetRotation(Surface.ROTATION_90)}
|
||||
* <p>
|
||||
* 切记,外部请勿直接调用 {@link #options(Preview.Builder)}
|
||||
*
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
public Preview options(@NonNull Preview.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置 {@link CameraSelector.Builder};可参考:{@link AspectRatioCameraConfig} 或 {@link ResolutionCameraConfig}
|
||||
* <p>
|
||||
* 如配置前置摄像头:{@code builder.requireLensFacing(CameraSelector.LENS_FACING_FRONT)}
|
||||
* <p>
|
||||
* 切记,外部请勿直接调用 {@link #options(CameraSelector.Builder)}
|
||||
*
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
public CameraSelector options(@NonNull CameraSelector.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 配置 {@link ImageAnalysis.Builder};可参考:{@link AspectRatioCameraConfig} 或 {@link ResolutionCameraConfig}
|
||||
* <p>
|
||||
* 如配置目标旋转角度为90度:{@code builder.setTargetRotation(Surface.ROTATION_90)}
|
||||
* <p>
|
||||
* 切记,外部请勿直接调用 {@link #options(ImageAnalysis.Builder)}
|
||||
*
|
||||
* @param builder
|
||||
* @return
|
||||
*/
|
||||
@NonNull
|
||||
public ImageAnalysis options(@NonNull ImageAnalysis.Builder builder) {
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -4,53 +4,89 @@ import android.content.Context;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Size;
|
||||
|
||||
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.camera.core.CameraSelector;
|
||||
import androidx.camera.core.ImageAnalysis;
|
||||
import androidx.camera.core.Preview;
|
||||
|
||||
/**
|
||||
* 相机配置:根据尺寸配置相机的目标图像,使输出分析的图像尽可能的接近屏幕尺寸
|
||||
* 相机配置:根据尺寸配置相机的目标图像大小,使输出分析的图像的分辨率尽可能的接近屏幕尺寸
|
||||
*
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public class ResolutionCameraConfig extends CameraConfig {
|
||||
|
||||
/**
|
||||
* 1080P
|
||||
*/
|
||||
public static final int IMAGE_QUALITY_1080P = 1080;
|
||||
/**
|
||||
* 720P
|
||||
*/
|
||||
public static final int IMAGE_QUALITY_720P = 720;
|
||||
|
||||
|
||||
private Size mTargetSize;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param context 上下文
|
||||
*/
|
||||
public ResolutionCameraConfig(Context context) {
|
||||
super();
|
||||
this(context, IMAGE_QUALITY_1080P);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param imageQuality 图像质量;此参数只是期望的图像质量,最终以实际计算结果为准
|
||||
*/
|
||||
public ResolutionCameraConfig(Context context, int imageQuality) {
|
||||
super();
|
||||
initTargetResolutionSize(context, imageQuality);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化 {@link #mTargetSize}
|
||||
*
|
||||
* @param context 上下文
|
||||
* @param imageQuality 图像质量;此参数只是期望的图像质量,最终以实际计算结果为准
|
||||
*/
|
||||
private void initTargetResolutionSize(Context context, int imageQuality) {
|
||||
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
|
||||
int width = displayMetrics.widthPixels;
|
||||
int height = displayMetrics.heightPixels;
|
||||
|
||||
LogUtils.d(String.format("displayMetrics:%d x %d",width,height));
|
||||
//因为为了保持流畅性和性能,限制在1080p,在此前提下尽可能的找到屏幕接近的分辨率
|
||||
LogUtils.d(String.format(Locale.getDefault(), "displayMetrics:%d x %d", width, height));
|
||||
// 因为为了保持流畅性和性能,尽可能的限制在imageQuality(默认:1080p),在此前提下尽可能的找到屏幕接近的分辨率
|
||||
if (width < height) {
|
||||
int size = Math.min(width, 1080);
|
||||
int size = Math.min(width, imageQuality);
|
||||
float ratio = width / (float) height;
|
||||
if(ratio > 0.7){//一般应用于平板
|
||||
mTargetSize = new Size(size, (int)(size / 3.0f * 4.0f));
|
||||
if (ratio > 0.7F) {
|
||||
// 一般应用于平板
|
||||
mTargetSize = new Size(size, (int) (size / 3.0F * 4.0F));
|
||||
} else {
|
||||
mTargetSize = new Size(size, (int)(size / 9.0f * 16.0f));
|
||||
mTargetSize = new Size(size, (int) (size / 9.0F * 16.0F));
|
||||
}
|
||||
} else {
|
||||
int size = Math.min(height, 1080);
|
||||
int size = Math.min(height, imageQuality);
|
||||
float ratio = height / (float) width;
|
||||
if(ratio > 0.7){//一般应用于平板
|
||||
mTargetSize = new Size((int)(size / 3.0f * 4.0f), size);
|
||||
if (ratio > 0.7F) {
|
||||
// 一般应用于平板
|
||||
mTargetSize = new Size((int) (size / 3.0F * 4.0F), size);
|
||||
} else {
|
||||
mTargetSize = new Size((int)(size / 9.0f * 16.0), size);
|
||||
mTargetSize = new Size((int) (size / 9.0F * 16.0F), size);
|
||||
}
|
||||
}
|
||||
LogUtils.d("targetSize:" + mTargetSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Preview options(@NonNull Preview.Builder builder) {
|
||||
|
||||
@@ -1,22 +1,5 @@
|
||||
package com.king.zxing.manager;
|
||||
|
||||
/*
|
||||
* Copyright (C) 2012 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
@@ -30,8 +13,8 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
private static final int INTERVAL_TIME = 200;
|
||||
|
||||
protected static final float DARK_LUX = 45.0f;
|
||||
protected static final float BRIGHT_LUX = 100.0f;
|
||||
protected static final float DARK_LUX = 45.0F;
|
||||
protected static final float BRIGHT_LUX = 100.0F;
|
||||
|
||||
/**
|
||||
* 光线太暗时,默认:照度45 lux
|
||||
@@ -74,7 +57,8 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
public void onSensorChanged(SensorEvent sensorEvent) {
|
||||
if (isLightSensorEnabled) {
|
||||
long currentTime = System.currentTimeMillis();
|
||||
if(currentTime - lastTime < INTERVAL_TIME){//降低频率
|
||||
if (currentTime - lastTime < INTERVAL_TIME) {
|
||||
// 降低频率
|
||||
return;
|
||||
}
|
||||
lastTime = currentTime;
|
||||
@@ -93,6 +77,7 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 设置光线足够暗的阈值(单位:lux)
|
||||
*
|
||||
* @param lightLux
|
||||
*/
|
||||
public void setDarkLightLux(float lightLux) {
|
||||
@@ -101,6 +86,7 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 设置光线足够明亮的阈值(单位:lux)
|
||||
*
|
||||
* @param lightLux
|
||||
*/
|
||||
public void setBrightLightLux(float lightLux) {
|
||||
@@ -118,6 +104,7 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 设置是否启用光线亮度传感器
|
||||
*
|
||||
* @param lightSensorEnabled
|
||||
*/
|
||||
public void setLightSensorEnabled(boolean lightSensorEnabled) {
|
||||
@@ -126,6 +113,7 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 设置光线亮度传感器监听器,只有在 {@link #isLightSensorEnabled} 为{@code true} 才有效
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
public void setOnLightSensorEventListener(OnLightSensorEventListener listener) {
|
||||
@@ -134,7 +122,6 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
public interface OnLightSensorEventListener {
|
||||
/**
|
||||
*
|
||||
* @param lightLux 当前检测到的光线照度值
|
||||
*/
|
||||
default void onSensorChanged(float lightLux) {
|
||||
@@ -143,6 +130,7 @@ public class AmbientLightManager implements SensorEventListener {
|
||||
|
||||
/**
|
||||
* 传感器改变事件
|
||||
*
|
||||
* @param dark 是否太暗了,当检测到的光线照度值小于{@link #darkLightLux}时,为{@code true}
|
||||
* @param lightLux 当前检测到的光线照度值
|
||||
*/
|
||||
|
||||
@@ -1,24 +1,7 @@
|
||||
package com.king.zxing.manager;
|
||||
/*
|
||||
* Copyright (C) 2010 ZXing authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.media.AudioManager;
|
||||
import android.media.MediaPlayer;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
@@ -28,7 +11,6 @@ import com.king.zxing.R;
|
||||
import com.king.zxing.util.LogUtils;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
@@ -85,7 +67,6 @@ public final class BeepManager implements MediaPlayer.OnErrorListener, Closeable
|
||||
AssetFileDescriptor file = context.getResources().openRawResourceFd(R.raw.zxl_beep);
|
||||
mediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
|
||||
mediaPlayer.setOnErrorListener(this);
|
||||
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
|
||||
mediaPlayer.setLooping(false);
|
||||
mediaPlayer.prepare();
|
||||
return mediaPlayer;
|
||||
|
||||
@@ -48,8 +48,9 @@ import com.king.zxing.DecodeFormatManager;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
* 二维码/条形码工具类:主要包括二维码/条形码的解析与生成
|
||||
*
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
public final class CodeUtils {
|
||||
@@ -63,6 +64,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @return
|
||||
@@ -73,6 +75,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param codeColor 二维码的颜色
|
||||
@@ -84,6 +87,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成我二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param logo logo大小默认占二维码的20%
|
||||
@@ -95,6 +99,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成我二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param logo logo大小默认占二维码的20%
|
||||
@@ -107,6 +112,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param logo 二维码中间的logo
|
||||
@@ -126,6 +132,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param logo 二维码中间的logo
|
||||
@@ -150,6 +157,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成二维码
|
||||
*
|
||||
* @param content 二维码的内容
|
||||
* @param heightPix 二维码的高
|
||||
* @param logo 二维码中间的logo
|
||||
@@ -194,6 +202,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 在二维码中间添加Logo图案
|
||||
*
|
||||
* @param src
|
||||
* @param logo
|
||||
* @param ratio logo所占比例 因为二维码的最大容错率为30%,所以建议ratio的范围小于0.3
|
||||
@@ -243,6 +252,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @return
|
||||
*/
|
||||
@@ -256,6 +266,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @return
|
||||
*/
|
||||
@@ -265,6 +276,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @param reqWidth 请求目标宽度,如果实际图片宽度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理
|
||||
* @param reqHeight 请求目标高度,如果实际图片高度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理
|
||||
@@ -276,6 +288,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @return
|
||||
*/
|
||||
@@ -285,6 +298,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @param hints 解析编码类型
|
||||
* @return
|
||||
@@ -299,6 +313,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析二维码图片
|
||||
*
|
||||
* @param bitmap 解析的图片
|
||||
* @return
|
||||
*/
|
||||
@@ -308,6 +323,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmap 解析的图片
|
||||
* @return
|
||||
*/
|
||||
@@ -317,6 +333,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmap 解析的图片
|
||||
* @param hints 解析编码类型
|
||||
* @return
|
||||
@@ -331,6 +348,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmapPath
|
||||
* @param hints 解析编码类型
|
||||
* @return
|
||||
@@ -341,6 +359,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmapPath 需要解析的图片路径
|
||||
* @param reqWidth 请求目标宽度,如果实际图片宽度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理
|
||||
* @param reqHeight 请求目标高度,如果实际图片高度大于此值,会自动进行压缩处理,当 reqWidth 和 reqHeight都小于或等于0时,则不进行压缩处理
|
||||
@@ -353,6 +372,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmap 解析的图片
|
||||
* @return
|
||||
*/
|
||||
@@ -362,6 +382,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param bitmap 解析的图片
|
||||
* @param hints 解析编码类型
|
||||
* @return
|
||||
@@ -372,6 +393,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 解析一维码/二维码图片
|
||||
*
|
||||
* @param source
|
||||
* @param hints
|
||||
* @return
|
||||
@@ -420,9 +442,9 @@ public final class CodeUtils {
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 压缩图片
|
||||
*
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
@@ -461,6 +483,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 获取RGBLuminanceSource
|
||||
*
|
||||
* @param bitmap
|
||||
* @return
|
||||
*/
|
||||
@@ -476,6 +499,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param desiredWidth
|
||||
* @param desiredHeight
|
||||
@@ -487,6 +511,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -503,6 +528,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param desiredWidth
|
||||
* @param desiredHeight
|
||||
@@ -516,6 +542,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -529,6 +556,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -543,6 +571,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -557,6 +586,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -571,6 +601,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 生成条形码
|
||||
*
|
||||
* @param content
|
||||
* @param format
|
||||
* @param desiredWidth
|
||||
@@ -618,6 +649,7 @@ public final class CodeUtils {
|
||||
|
||||
/**
|
||||
* 条形码下面添加文本信息
|
||||
*
|
||||
* @param src
|
||||
* @param code
|
||||
* @param textSize
|
||||
@@ -662,5 +694,4 @@ public final class CodeUtils {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -16,9 +16,10 @@
|
||||
*/
|
||||
package com.king.zxing.util;
|
||||
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author Jenly <a href="mailto:jenly1314@gmail.com">Jenly</a>
|
||||
*/
|
||||
@@ -28,10 +29,14 @@ public class LogUtils {
|
||||
|
||||
public static final String VERTICAL = "|";
|
||||
|
||||
/** 是否显示Log日志 */
|
||||
/**
|
||||
* 是否显示Log日志
|
||||
*/
|
||||
private static boolean isShowLog = true;
|
||||
|
||||
/** Log日志优先权 */
|
||||
/**
|
||||
* Log日志优先权
|
||||
*/
|
||||
private static int priority = 1;
|
||||
|
||||
/**
|
||||
@@ -97,20 +102,21 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* 根据堆栈生成TAG
|
||||
*
|
||||
* @return TAG|className.methodName(fileName:lineNumber)
|
||||
*/
|
||||
private static String generateTag(StackTraceElement caller) {
|
||||
String tag = TAG_FORMAT;
|
||||
String callerClazzName = caller.getClassName();
|
||||
callerClazzName = callerClazzName.substring(callerClazzName.lastIndexOf(".") + 1);
|
||||
tag = String.format(tag,callerClazzName, caller.getMethodName(),caller.getFileName(),caller.getLineNumber());
|
||||
tag = String.format(Locale.getDefault(), tag, callerClazzName, caller.getMethodName(), caller.getFileName(), caller.getLineNumber());
|
||||
return new StringBuilder().append(TAG).append(VERTICAL).append(tag).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取堆栈
|
||||
* @param n
|
||||
* n=0 VMStack
|
||||
*
|
||||
* @param n n=0 VMStack
|
||||
* n=1 Thread
|
||||
* n=3 CurrentStack
|
||||
* n=4 CallerStack
|
||||
@@ -123,6 +129,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* 获取调用方的堆栈TAG
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static String getCallerStackLogTag() {
|
||||
@@ -130,7 +137,6 @@ public class LogUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param t
|
||||
* @return
|
||||
*/
|
||||
@@ -142,6 +148,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.v
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void v(String msg) {
|
||||
@@ -164,6 +171,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.d
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void d(String msg) {
|
||||
@@ -185,6 +193,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.i
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void i(String msg) {
|
||||
@@ -206,6 +215,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.w
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void w(String msg) {
|
||||
@@ -227,6 +237,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.e
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void e(String msg) {
|
||||
@@ -248,6 +259,7 @@ public class LogUtils {
|
||||
|
||||
/**
|
||||
* Log.wtf
|
||||
*
|
||||
* @param msg
|
||||
*/
|
||||
public static void wtf(String msg) {
|
||||
@@ -312,3 +324,4 @@ public class LogUtils {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 检测是否授权
|
||||
*
|
||||
* @param context
|
||||
* @param permission
|
||||
* @return 返回{@code true} 表示已授权,{@code false}表示未授权
|
||||
@@ -30,6 +31,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限
|
||||
*
|
||||
* @param activity
|
||||
* @param permission
|
||||
* @param requestCode
|
||||
@@ -40,6 +42,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限
|
||||
*
|
||||
* @param fragment
|
||||
* @param permission
|
||||
* @param requestCode
|
||||
@@ -50,6 +53,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限
|
||||
*
|
||||
* @param activity
|
||||
* @param permissions
|
||||
* @param requestCode
|
||||
@@ -60,6 +64,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限
|
||||
*
|
||||
* @param fragment
|
||||
* @param permissions
|
||||
* @param requestCode
|
||||
@@ -70,6 +75,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限结果
|
||||
*
|
||||
* @param requestPermission 请求的权限
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
@@ -89,6 +95,7 @@ public class PermissionUtils {
|
||||
|
||||
/**
|
||||
* 请求权限结果
|
||||
*
|
||||
* @param requestPermissions 请求的权限
|
||||
* @param permissions
|
||||
* @param grantResults
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.5 KiB |
12
zxing-lite/src/main/res/drawable/zxl_flashlight_off.xml
Normal file
12
zxing-lite/src/main/res/drawable/zxl_flashlight_off.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="30dp"
|
||||
android:height="30dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m755.2,209.9c-17.2,-17.4 -40.2,-26.9 -64.5,-26.9l-357.2,0c-50.3,0 -91.3,40.9 -91.3,91.3l0,105.1c0,77.3 36.3,149.7 97.7,196.1l0,300.3c0,50.3 40.9,91.3 91.3,91.3l161.5,0c50.3,0 91.3,-40.9 91.3,-91.3l0,-300.3c61.4,-46.4 97.7,-118.7 97.7,-196.1l0,-104.9c0.2,-24.4 -9.3,-47.3 -26.5,-64.6zM333.5,230.8l357.1,0c11.6,0 22.5,4.5 30.7,12.8c8.2,8.2 12.7,19.1 12.6,30.8l0,42.9l-443.9,0l0,-43c0,-24 19.5,-43.5 43.5,-43.5zM646.7,543.3c-6.6,4.4 -10.5,11.9 -10.5,19.8l0,312.6c0,24 -19.5,43.5 -43.5,43.5l-161.4,0c-24,0 -43.5,-19.5 -43.5,-43.5l0,-312.6c0,-7.9 -3.9,-15.4 -10.5,-19.8c-54,-36.5 -86.3,-96.8 -87.1,-161.7l443.7,0c-0.8,64.9 -33.2,125.2 -87.2,161.7z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m543,690.4l-62,0c-0.7,0 -1.2,-0.5 -1.2,-1.2l0,-169.4c0,-0.7 0.5,-1.2 1.2,-1.2l62,0c0.7,0 1.2,0.5 1.2,1.2l0,169.4c0,0.7 -0.5,1.2 -1.2,1.2z" />
|
||||
</vector>
|
||||
27
zxing-lite/src/main/res/drawable/zxl_flashlight_on.xml
Normal file
27
zxing-lite/src/main/res/drawable/zxl_flashlight_on.xml
Normal file
@@ -0,0 +1,27 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="30dp"
|
||||
android:height="30dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m755.2,209.9c-17.2,-17.4 -40.2,-26.9 -64.5,-26.9l-357.2,0c-50.3,0 -91.3,40.9 -91.3,91.3l0,105.1c0,77.3 36.3,149.7 97.7,196.1l0,300.3c0,50.3 40.9,91.3 91.3,91.3l161.5,0c50.3,0 91.3,-40.9 91.3,-91.3l0,-300.3c61.4,-46.4 97.7,-118.7 97.7,-196.1l0,-104.9c0.2,-24.4 -9.3,-47.3 -26.5,-64.6zM333.5,230.8l357.1,0c11.6,0 22.5,4.5 30.7,12.8c8.2,8.2 12.7,19.1 12.6,30.8l0,42.9l-443.9,0l0,-43c0,-24 19.5,-43.5 43.5,-43.5zM646.7,543.3c-6.6,4.4 -10.5,11.9 -10.5,19.8l0,312.6c0,24 -19.5,43.5 -43.5,43.5l-161.4,0c-24,0 -43.5,-19.5 -43.5,-43.5l0,-312.6c0,-7.9 -3.9,-15.4 -10.5,-19.8c-54,-36.5 -86.3,-96.8 -87.1,-161.7l443.7,0c-0.8,64.9 -33.2,125.2 -87.2,161.7z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="m543,690.4l-62,0c-0.7,0 -1.2,-0.5 -1.2,-1.2l0,-169.4c0,-0.7 0.5,-1.2 1.2,-1.2l62,0c0.7,0 1.2,0.5 1.2,1.2l0,169.4c0,0.7 -0.5,1.2 -1.2,1.2z" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M682.5,77.5a53.5,26.5 116.5,1 0,45 28.4a53.5,26.5 116.5,1 0,-45 -28.4z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M482,80a30,68 0,1 0,60 0a30,68 0,1 0,-60 0z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M296.5,105.6a53.5,26.5 63.5,1 0,45 -28.4a53.5,26.5 63.5,1 0,-45 28.4z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#FFFFFF" />
|
||||
</vector>
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_selected="true" android:drawable="@drawable/zxl_flashlight_on"/>
|
||||
<item android:drawable="@drawable/zxl_flashlight_on" android:state_selected="true" />
|
||||
<item android:drawable="@drawable/zxl_flashlight_off" />
|
||||
</selector>
|
||||
@@ -7,15 +7,18 @@
|
||||
android:id="@+id/previewView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<com.king.zxing.ViewfinderView
|
||||
android:id="@+id/viewfinderView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/ivFlashlight"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/zxl_flashlight_selector"
|
||||
android:layout_marginTop="@dimen/zxl_flashlight_margin_top" />
|
||||
android:layout_marginTop="@dimen/zxl_flashlight_margin_top"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/zxl_flashlight_selector" />
|
||||
</FrameLayout>
|
||||
@@ -40,6 +40,17 @@
|
||||
<enum name="right" value="3"/>
|
||||
<enum name="bottom" value="4"/>
|
||||
</attr>
|
||||
<attr name="pointColor" format="color"/>
|
||||
<attr name="pointStrokeColor" format="color"/>
|
||||
<attr name="pointRadius" format="dimension"/>
|
||||
<attr name="pointStrokeRatio" format="float"/>
|
||||
<attr name="pointDrawable" format="reference"/>
|
||||
<attr name="showPointAnim" format="boolean"/>
|
||||
<attr name="laserDrawable" format="reference"/>
|
||||
<attr name="viewfinderStyle" format="enum">
|
||||
<enum name="classic" value="0"/>
|
||||
<enum name="popular" value="1"/>
|
||||
</attr>
|
||||
</declare-styleable>
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<color name="viewfinder_frame">#7F1FB3E2</color>
|
||||
<color name="viewfinder_corner">#FF1FB3E2</color>
|
||||
<color name="viewfinder_laser">#FF1FB3E2</color>
|
||||
<color name="viewfinder_point">#FF1FB3E2</color>
|
||||
<color name="viewfinder_text_color">#FFC0C0C0</color>
|
||||
|
||||
<color name="zxl_capture_status_bar_color">#00000000</color>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<dimen name="zxl_flashlight_margin_top">80dp</dimen>
|
||||
<dimen name="zxl_flashlight_margin_top">90dp</dimen>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user