二维码扫描之Zxing的一次实操记录,配合添加手电筒开关
刚好项目中涉及到了二维码扫描的功能,就记录下Zxing的使用过程,个人擅自添加了手电筒到界面,可以给大家一些参考。
首先看下效果图如下
这个红色的手电筒就是自定义加上去的,点击可以切换扫描时候的闪光灯的开关状态,下面看下一步一步实现的步骤。
1. 本实例基于AS 3.1.2的版本实现,所以看下依赖引入的实例。
implementation 'com.github.zagum:Android-SwitchIcon:1.3.7' implementation('com.journeyapps:zxing-android-embedded:3.6.0') { transitive = false } implementation 'com.google.zxing:core:3.3.0'
不过在引入之前需要在项目根目录的build.gradle中添加如下maven依赖地址
allprojects {
repositories {
maven { url "https://jitpack.io" }
jcenter()
}
}
放上两个相关项目的Github地址,向原作者致敬
Android-SwitchIcon:https://github.com/zagum/Android-SwitchIcon
zxing-android-embedded : https://github.com/journeyapps/zxing-android-embedded
本实例使用了ButterKnife依赖,想偷懒的同学也记得一并引入。
2.看下准备工作,首先准备两个按钮的素材,这里呢我尝试了使用Vector 矢量图的素材,先把资源给大家。
首先是ic_torch.xml
<vector android:height="24dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#ffffff" android:pathData="M514.38,543.73c16.17,0 29.27,14.4 29.27,32.17v81.45c0,17.76 -13.11,32.17 -29.27,32.17s-29.27,-14.4 -29.27,-32.17v-81.45c0,-17.76 13.11,-32.17 29.27,-32.17zM254.67,0h519.43c34.78,0 63.07,28.28 63.07,63.07v106.3c0,183.31 -100.17,293.63 -144.7,332.03v458.96c0,35.08 -28.44,63.64 -63.51,63.64L398.5,1024c-35.07,0 -62.21,-28.56 -62.21,-63.64L336.29,501.44c-44.52,-38.21 -144.7,-147.66 -144.7,-332.07L191.59,63.07C191.6,28.28 219.89,0 254.67,0zM612.48,952.32v-89.98L416.28,862.34v89.98L612.48,952.32zM762.3,234.46h-495.92c23.89,138.86 129.51,220.74 130.71,221.56 12.68,8.69 10.96,20.01 10.96,34.97v322.06h212.66L620.71,490.99c0,-14.9 -2.48,-26.17 10.11,-34.87 4.76,-3.36 107.66,-82.8 131.48,-221.66zM266.31,68.99v105.03h496.15L762.45,68.99L266.31,68.99z"/> </vector>
另一个是扫描按钮ic_scan.xml
<vector android:height="24dp" android:viewportHeight="1024" android:viewportWidth="1024" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#58aeae" android:pathData="M963.38,963.36L686.43,963.36v60.62L1024,1023.98L1024,692.67h-60.62v270.69zM60.62,692.67L0,692.67v331.31h337.57v-60.62L60.62,963.36v-270.69zM686.43,0v60.62h276.95v270.69L1024,331.31L1024,0L686.43,0zM60.62,60.62h276.95L337.57,0L0,0v331.31h60.62L60.62,60.62zM220.78,491.24L508.08,491.24L508.08,203.94L220.78,203.94L220.78,491.24zM281.4,264.56L447.46,264.56v166.06L281.4,430.62L281.4,264.56zM830.39,529.79L543.09,529.79v287.3h287.3L830.39,529.79zM769.77,756.47L603.71,756.47v-166.06L769.77,590.41v166.06zM767.99,205.92h60.62v285.13h-60.62L767.99,205.92zM545.07,205.92h113.34v113.34h-113.34v-113.34zM545.07,374.14h113.34v113.34h-113.34L545.07,374.14zM446.86,532.95h60.62L507.48,818.08h-60.62L446.86,532.95zM223.92,532.96h113.34v113.34h-113.34L223.92,532.96zM223.92,701.18h113.34L337.26,814.52h-113.34L223.92,701.18z"/> </vector>
两个文件存放的位置在drawable文件夹中
3.素材准备好了之后开始处理界面和逻辑代码了,看下流程和实现。
首先是MainActivity点击按钮跳转
public class MainActivity extends AppCompatActivity { @BindView(R.id.scan_btn) ImageView scanBtn; @BindView(R.id.scan_result) TextView scanResult; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ButterKnife.bind(this); } @OnClick(R.id.scan_btn) public void onClick() { // 跳转到扫码界面进行扫码 IntentIntegrator intentIntegrator = new IntentIntegrator(MainActivity.this); intentIntegrator .setDesiredBarcodeFormats(IntentIntegrator.ALL_CODE_TYPES) .setPrompt("将二维码/条码放入框内,即可自动扫描")//写那句提示的话 .setOrientationLocked(false)//扫描方向固定 .setCaptureActivity(ScanActivity.class) // 设置自定义的activity .initiateScan(); // 初始化扫描 } // Get the results: @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); if (result != null) { if (result.getContents() == null) { Toast.makeText(this, R.string.scan_cancel, Toast.LENGTH_LONG).show(); } else { Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show(); scanResult.setText("扫描结果:\n"+result.getContents()); } } else { super.onActivityResult(requestCode, resultCode, data); } } }
布局文件activity_main.xml很简单,就只有一个按钮,点击后会跳转到ScanActivity页面,在ScanActivity中可以增加些逻辑,因为activity_main.xml比较简单,这里就不贴出来了。按钮素材已经给了,怎么放的话大家可以自由发挥。看下ScanActivity写法,其中的注释写的很清楚了,其余的也是按照文档上的标准的东西来写的,拷贝用的话问题基本不大。
public class ScanActivity extends AppCompatActivity { @BindView(R.id.dbv_custom) DecoratedBarcodeView dbvCustom; @BindView(R.id.switch_light) SwitchIconView switchLight; private CaptureManager captureManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan); ButterKnife.bind(this); // 如果没有闪光灯功能,就去掉相关按钮 if (!hasFlash()) { switchLight.setVisibility(View.GONE); } captureManager = new CaptureManager(this, dbvCustom); captureManager.initializeFromIntent(getIntent(), savedInstanceState); captureManager.decode(); } @Override protected void onPause() { super.onPause(); captureManager.onPause(); } @Override protected void onResume() { super.onResume(); captureManager.onResume(); } @Override protected void onDestroy() { super.onDestroy(); captureManager.onDestroy(); } @Override public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) { super.onSaveInstanceState(outState, outPersistentState); captureManager.onSaveInstanceState(outState); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { return dbvCustom.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event); } // 判断是否有闪光灯功能 private boolean hasFlash() { return getApplicationContext().getPackageManager() .hasSystemFeature(PackageManager.FEATURE_CAMERA_FLASH); } @OnClick({R.id.switch_light, R.id.dbv_custom}) public void onClick(View view) { switch (view.getId()) { case R.id.switch_light: Log.d("CJT" , "switch_light -- onClick"); switchLight.switchState(true); if(switchLight.isIconEnabled()){ dbvCustom.setTorchOn(); // 打开手电筒 }else{ dbvCustom.setTorchOff(); // 关闭手电筒 } break; case R.id.dbv_custom: Log.d("CJT" , "dbv_custom -- onClick"); break; } } }
贴出来对应的布局文件。acitivity_scan.xml
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".activity.ScanActivity"> <com.journeyapps.barcodescanner.DecoratedBarcodeView android:id="@+id/dbv_custom" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:zxing_framing_rect_height="200dp" app:zxing_framing_rect_width="200dp" app:zxing_preview_scaling_strategy="fitXY" app:zxing_use_texture_view="true" > <com.github.zagum.switchicon.SwitchIconView android:id="@+id/switch_light" android:layout_width="42dp" android:layout_height="42dp" android:layout_marginBottom="45dp" android:layout_marginEnd="8dp" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:layout_gravity="center" android:layout_marginTop="200dp" app:layout_constraintBottom_toBottomOf="@+id/dbv_custom" app:layout_constraintEnd_toEndOf="@+id/dbv_custom" app:layout_constraintStart_toStartOf="@+id/dbv_custom" app:si_animation_duration="200" app:si_disabled_alpha=".3" app:si_disabled_color="@color/state_off" app:si_enabled="false" app:si_no_dash="true" app:si_tint_color="@color/state_on" app:srcCompat="@drawable/ic_torch" /> </com.journeyapps.barcodescanner.DecoratedBarcodeView> </android.support.constraint.ConstraintLayout>
布局用的是默认的约束布局,其实用熟练了不比RelativLayout差,当然布局啥的也是根据大家的喜好自己使用,其中DecoratedBarcodeView是引入的Zxing依赖包自定义的一个布局,看了源码是继承自FrameLayout的,所以当然可以在这个布局上再添加些东西了,所以直接添加了一个SwitchIconView的控件,记得调下位置,居中靠底部就好了,这个SwitchIconView也有需要注意的地方
a.定义好si_disable_color和si_tint_color连个颜色资源,分别是切换状态时候的不同颜色
b.设置好srcCompat资源,这个最好使用矢量图来设置
c.si_no_dash是指在switchicon在off状态是否加斜杠,默然不加,duration是指动画时间,alpha是指off下的透明度
4.总结:在扫描界面扫码后得到的结果会回调MainActivty中的onActivityResult方法,把得到的结果返回。大家可以根据需要处理了,我这里主要演示在扫码界面使用第三方的控件定制了一个手电筒的开关按钮,控制闪光灯的开关,大家可以多方位的去实践创造更多的例子,Github确实给我们提供了很多便利,感谢前人的无私奉献。