首页 Java java教程 Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

Jan 13, 2017 am 10:41 AM

先给大家展示下效果图:

Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

扫描内容是下面这张,二维码是用zxing库生成的

Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java

package com.zxing.activity;
import java.io.IOException;
import java.util.Vector;
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Handler;
import android.os.Vibrator;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.widget.Toast;
import com.ericssonlabs.R;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.zxing.camera.CameraManager;
import com.zxing.decoding.CaptureActivityHandler;
import com.zxing.decoding.CaptureActivityHandler.DecodeCallback;
import com.zxing.decoding.InactivityTimer;
import com.zxing.view.ViewfinderView;
/**
* Initial the camera
* @author Ryan.Tang
* @modifier Lemon
* @use extends CaptureActivity并且在setContentView方法后调用init方法
*/
public abstract class CaptureActivity extends Activity implements Callback, DecodeCallback {
// private static final String TAG = "CaptureActivity";
protected Activity context;
protected SurfaceView surfaceView;
protected ViewfinderView viewfinderView;
/**初始化,必须在setContentView之后
* @param context
* @param viewfinderView
*/
protected void init(Activity context, SurfaceView surfaceView, ViewfinderView viewfinderView) {
this.context = context;
this.surfaceView = surfaceView;
this.viewfinderView = viewfinderView;
CameraManager.init(getApplication());
hasSurface = false;
inactivityTimer = new InactivityTimer(this);
}
private CaptureActivityHandler handler;
private boolean hasSurface;
private Vector<BarcodeFormat> decodeFormats;
private String characterSet;
private InactivityTimer inactivityTimer;
private MediaPlayer mediaPlayer;
private boolean playBeep;
private static final float BEEP_VOLUME = .f;
private boolean vibrate;
@Override
protected void onResume() {
super.onResume();
SurfaceHolder surfaceHolder = surfaceView.getHolder();
if (hasSurface) {
initCamera(surfaceHolder);
} else {
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
decodeFormats = null;
characterSet = null;
playBeep = true;
AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
playBeep = false;
}
initBeepSound();
vibrate = true;
}
@Override
protected void onPause() {
super.onPause();
if (handler != null) {
handler.quitSynchronously();
handler = null;
}
CameraManager.get().closeDriver();
}
@Override
protected void onDestroy() {
inactivityTimer.shutdown();
super.onDestroy();
}
public static final String RESULT_QRCODE_STRING = "RESULT_QRCODE_STRING";
/**
* Handler scan result
* @param result
* @param barcode
*/
public void handleDecode(Result result, Bitmap barcode) {
inactivityTimer.onActivity();
playBeepSoundAndVibrate();
String resultString = result.getText();
//FIXME
if (resultString.equals("")) {
Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
}
setResult(RESULT_OK, new Intent().putExtra(RESULT_QRCODE_STRING, resultString));
finish();
}
private void initCamera(SurfaceHolder surfaceHolder) {
try {
CameraManager.get().openDriver(surfaceHolder);
} catch (IOException ioe) {
return;
} catch (RuntimeException e) {
return;
}
if (handler == null) {
handler = new CaptureActivityHandler(this, decodeFormats,
characterSet, viewfinderView, this);
}
}
@Override
public void drawViewfinder() {
viewfinderView.drawViewfinder(); 
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!hasSurface) {
hasSurface = true;
initCamera(holder);
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
hasSurface = false;
}
public Handler getHandler() {
return handler;
}
private void initBeepSound() {
if (playBeep && mediaPlayer == null) {
// The volume on STREAM_SYSTEM is not adjustable, and users found it
// too loud,
// so we now play on the music stream.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
mediaPlayer = new MediaPlayer();
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setOnCompletionListener(beepListener);
AssetFileDescriptor file = getResources().openRawResourceFd(
R.raw.beep);
try {
mediaPlayer.setDataSource(file.getFileDescriptor(),
file.getStartOffset(), file.getLength());
file.close();
mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
mediaPlayer.prepare();
} catch (IOException e) {
mediaPlayer = null;
}
}
}
private static final long VIBRATE_DURATION = L;
private void playBeepSoundAndVibrate() {
if (playBeep && mediaPlayer != null) {
mediaPlayer.start();
}
if (vibrate) {
Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
vibrator.vibrate(VIBRATE_DURATION);
}
}
/**
* When the beep has finished playing, rewind to queue up another one.
*/
private final OnCompletionListener beepListener = new OnCompletionListener() {
public void onCompletion(MediaPlayer mediaPlayer) {
mediaPlayer.seekTo();
}
};
}
登录后复制

使用方法: 新建一个Activity继承CaptureActivity并且在setContentView方法后调用init方法即可。
示例:

CameraScanActivity.java

package zuo.biao.activity;
import zuo.biao.R;
import zuo.biao.library.interfaces.OnBottomDragListener;
import zuo.biao.util.ActivityUtil;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import com.zxing.activity.CaptureActivity;
import com.zxing.camera.CameraManager;
import com.zxing.view.ViewfinderView;
/**扫描二维码Activity
* @author Lemon
* @use 参考zuo.biao.library.ModelActivity
*/
public class CameraScanActivity extends CaptureActivity implements Callback, OnClickListener, OnBottomDragListener {
public static final String TAG = "CameraScanActivity";
//启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
/**启动这个Activity的Intent
* @param context
* @param title
* @return
*/
public static Intent createIntent(Context context) {
return new Intent(context, CameraScanActivity.class);
}
//启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.camera_scan_activity);
init(this, (SurfaceView) findViewById(R.id.svCameraScan), (ViewfinderView) findViewById(R.id.vfvCameraScan));
//功能归类分区方法,必须调用<<<<<<<<<<
initView();
initData();
initListener();
//功能归类分区方法,必须调用>>>>>>>>>>
}
//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public void initView() {//必须调用
}
//UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public void initData() {//必须调用
}
//data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//listener事件监听区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public void initListener() {//必须调用
findViewById(R.id.tvCameraScanReturn).setOnClickListener(this);
findViewById(R.id.ivCameraScanReturn).setOnClickListener(this);
findViewById(R.id.ivCameraScanLight).setOnClickListener(this);
findViewById(R.id.ivCameraScanMyQRCode).setOnClickListener(this);
}
//系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
@Override
public void onDragBottom(boolean rightToLeft) {
if (rightToLeft) {
return;
}
finish();
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.tvCameraScanReturn:
case R.id.ivCameraScanReturn:
onDragBottom(false);
break;
case R.id.ivCameraScanLight:
switchLight(! isOpen);
break;
case R.id.ivCameraScanMyQRCode:
//
break;
default:
break;
}
}
private boolean isOpen = false;
/**打开或关闭闪关灯
* @param open
*/
private void switchLight(boolean open) {
if (open == isOpen) {
return;
}
isOpen = CameraManager.get().switchLight(open);
}
//类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//listener事件监听区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
//内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
}
登录后复制

CameraScanActivity布局文件camera_scan_activity.xml

<?xml version="." encoding="utf-"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="@style/activity_page" >
<SurfaceView
android:id="@+id/svCameraScan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<!-- 必须在最底层,且不能指定宽高,否则扫描读取很难实现 -->
<com.zxing.view.ViewfinderView
android:id="@+id/vfvCameraScan"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
style="@style/ll_vertical_match_match"
android:baselineAligned="false" >
<RelativeLayout
style="@style/topbar_bg"
android:background="@color/white_alpha" >
<TextView
android:id="@+id/tvCameraScanReturn"
style="@style/topbar_left_btn"
android:text=" " />
<TextView
style="@style/topbar_title"
android:layout_centerHorizontal="true"
android:text="扫一扫" />
</RelativeLayout>
<LinearLayout
style="@style/ll_vertical_match_match"
android:layout_gravity="center_horizontal"
android:layout_weight="" >
<TextView
style="@style/text_middle_white"
android:layout_margin="dp"
android:text="@string/camera_scan_remind" />
</LinearLayout>
<LinearLayout
style="@style/ll_horizontal_match_wrap"
android:layout_gravity="bottom"
android:background="@color/white_alpha"
android:gravity="center" >
<LinearLayout
style="@style/ll_vertical_wrap_wrap"
android:layout_margin="dp"
android:paddingBottom="dp"
android:paddingLeft="dp"
android:paddingRight="dp"
android:paddingTop="dp" >
<ImageView
android:id="@+id/ivCameraScanReturn"
style="@style/wrap_wrap"
android:background="@drawable/cilcle_gray_to_white"
android:padding="dp"
android:src="@drawable/back_black_light" />
<TextView
style="@style/text_small"
android:layout_marginTop="dp"
android:text="返回" />
</LinearLayout>
<LinearLayout
style="@style/ll_vertical_wrap_wrap"
android:layout_margin="dp"
android:paddingBottom="dp"
android:paddingLeft="dp"
android:paddingRight="dp"
android:paddingTop="dp" >
<ImageView
android:id="@+id/ivCameraScanLight"
style="@style/wrap_wrap"
android:background="@drawable/cilcle_gray_to_white"
android:padding="dp"
android:src="@drawable/flash_light" />
<TextView
style="@style/text_small"
android:layout_marginTop="dp"
android:text="开灯/关灯" />
</LinearLayout>
<LinearLayout
style="@style/ll_vertical_wrap_wrap"
android:layout_margin="dp"
android:paddingBottom="dp"
android:paddingLeft="dp"
android:paddingRight="dp"
android:paddingTop="dp" >
<ImageView
android:id="@+id/ivCameraScanMyQRCode"
style="@style/wrap_wrap"
android:background="@drawable/cilcle_gray_to_white"
android:padding="dp"
android:src="@drawable/qrcode" />
<TextView
style="@style/text_small"
android:layout_marginTop="dp"
android:text="我的名片" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</FrameLayout>
登录后复制

布局文件因为使用了ZBLibrary中的一些style,color等,只有这个layout的话会出现一些错误。自己新建一个layout文件并把ViewfinderView放到最外层布局文件内就行了。当然下载好下面附上的源码就没这问题了。

对了,记得在AndroidManifest.xml中加上这些权限:

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
登录后复制

附源码(含使用方法)

Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

GitHub源码      https://github.com/TommyLemon/Android-ZBLibrary 

开源中国源码    http://git.oschina.net/Lemon19950301/Android-ZBLibrary 

关于Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题就给大家介绍到这里,以上内容有点长,希望大家能耐心看完,有任何问题欢迎给我留言,小编会及时回复大家的,在此也非常感谢大家对PHP中文网的支持!

更多Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题相关文章请关注PHP中文网!


本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

如何通过 OAuth2.0 的 scope 机制限制嵌套 H5 页面对特定接口的访问权限? 如何通过 OAuth2.0 的 scope 机制限制嵌套 H5 页面对特定接口的访问权限? Apr 19, 2025 pm 02:30 PM

如何利用OAuth2.0的access_token实现接口访问权限的控制?在OAuth2.0的应用中,如何确保嵌套在A公司app内的...

在后端开发中,如何区分service层和dao层的职责? 在后端开发中,如何区分service层和dao层的职责? Apr 19, 2025 pm 01:51 PM

探讨后端开发中的分层架构在后端开发中,分层架构是一种常见的设计模式,通常包括controller、service和dao三层�...

在Java远程调试中,如何正确获取远程服务器上的常量值? 在Java远程调试中,如何正确获取远程服务器上的常量值? Apr 19, 2025 pm 01:54 PM

Java远程调试中常量获取的疑问解答在使用Java进行远程调试时,许多开发者可能会遇到一些难以理解的现象。其�...

初学后端开发,Java项目管理工具该如何选择? 初学后端开发,Java项目管理工具该如何选择? Apr 19, 2025 pm 02:15 PM

初学后端的Java项目管理工具选择困惑对于刚开始学习后端开发的朋友来说,选择合适的项目管理工具是至关重�...

分布式系统中最终一致性:如何应用以及如何弥补数据不一致? 分布式系统中最终一致性:如何应用以及如何弥补数据不一致? Apr 19, 2025 pm 02:24 PM

探究最终一致性在分布式系统中的应用分布式事务处理一直是分布式系统架构中的一个难题。为了解决各个子事...

在YARN上提交PyFlink作业时,为什么会报错无法找到Python脚本? 在YARN上提交PyFlink作业时,为什么会报错无法找到Python脚本? Apr 19, 2025 pm 02:06 PM

在YARN上提交PyFlink作业时报错无法找到Python脚本的原因分析当你尝试通过YARN提交一个PyFlink作业时,可能会遇到�...

在Java中如何在项目启动时动态修改easypoi中@Excel注解的savePath参数? 在Java中如何在项目启动时动态修改easypoi中@Excel注解的savePath参数? Apr 19, 2025 pm 02:09 PM

在Java中如何动态配置实体类注解的参数在开发过程中,我们经常会遇到需要根据不同环境动态配置注解参数的�...

Tomcat加载Spring-Web模块时,SPI机制真的破坏了Java类加载器的可见性原则吗? Tomcat加载Spring-Web模块时,SPI机制真的破坏了Java类加载器的可见性原则吗? Apr 19, 2025 pm 02:18 PM

Tomcat加载Spring-Web模块时SPI机制的类加载行为分析Tomcat在加载Spring-Web模块时,为了发现并使用Spring-Web提供的Servle...

See all articles