当前位置: 移动技术网 > IT编程>移动开发>Android > Android开发框架之自定义ZXing二维码扫描界面并解决取景框拉伸问题

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

至今未解事件:夺命洞穴惊全国,石家庄桥东区教育局,营口汽车站

先给大家展示下效果图:

扫描内容是下面这张,二维码是用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" />

附源码(含使用方法)

github源码      https://github.com/tommylemon/android-zblibrary 

开源中国源码   

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网