自定义ZXing二维码扫描界面并解决取景框拉伸等问题_移动开发_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > 移动开发 > 自定义ZXing二维码扫描界面并解决取景框拉伸等问题

自定义ZXing二维码扫描界面并解决取景框拉伸等问题

 2016/6/7 5:30:48  TommyLemon  程序员俱乐部  我要评论(0)
  • 摘要:先看效果扫描内容是下面这张,二维码是用zxing库生成的由于改了好几个类,还是去年的事都忘得差不多了,所以只能上这个类的代码了,主要就是改了这个CaptureActivity.java1packagecom.zxing.activity;23importjava.io.IOException;4importjava.util.Vector;56importandroid.app.Activity;7importandroid.content.Intent;8importandroid
  • 标签:解决 问题 自定义 二维码

先看效果

 

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

 

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

 

  1 package com.zxing.activity;
  2 
  3 import java.io.IOException;
  4 import java.util.Vector;
  5 
  6 import android.app.Activity;
  7 import android.content.Intent;
  8 import android.content.res.AssetFileDescriptor;
  9 import android.graphics.Bitmap;
 10 import android.media.AudioManager;
 11 import android.media.MediaPlayer;
 12 import android.media.MediaPlayer.OnCompletionListener;
 13 import android.os.Handler;
 14 import android.os.Vibrator;
 15 import android.view.SurfaceHolder;
 16 import android.view.SurfaceHolder.Callback;
 17 import android.view.SurfaceView;
 18 import android.widget.Toast;
 19 
 20 import com.ericssonlabs.R;
 21 import com.google.zxing.BarcodeFormat;
 22 import com.google.zxing.Result;
 23 import com.zxing.camera.CameraManager;
 24 import com.zxing.decoding.CaptureActivityHandler;
 25 import com.zxing.decoding.CaptureActivityHandler.DecodeCallback;
 26 import com.zxing.decoding.InactivityTimer;
 27 import com.zxing.view.ViewfinderView;
 28 /**
 29  * Initial the camera
 30  * @author Ryan.Tang
 31  * @modifier Lemon
 32  * @use extends CaptureActivity并且在setContentView方法后调用init方法
 33  */
 34 public abstract class CaptureActivity extends Activity implements Callback, DecodeCallback {
 35     //    private static final String TAG = "CaptureActivity";
 36 
 37     protected Activity context;
 38     protected SurfaceView surfaceView;
 39     protected ViewfinderView viewfinderView;
 40     /**初始化,必须在setContentView之后
 41      * @param context
 42      * @param viewfinderView
 43      */
 44     protected void init(Activity context, SurfaceView surfaceView, ViewfinderView viewfinderView) {
 45         this.context = context;
 46         this.surfaceView = surfaceView;
 47         this.viewfinderView = viewfinderView;
 48 
 49         CameraManager.init(getApplication());
 50 
 51         hasSurface = false;
 52         inactivityTimer = new InactivityTimer(this);
 53     }
 54 
 55 
 56     private CaptureActivityHandler handler;
 57     private boolean hasSurface;
 58     private Vector<BarcodeFormat> decodeFormats;
 59     private String characterSet;
 60     private InactivityTimer inactivityTimer;
 61     private MediaPlayer mediaPlayer;
 62     private boolean playBeep;
 63     private static final float BEEP_VOLUME = 0.10f;
 64     private boolean vibrate;
 65 
 66 
 67     @Override
 68     protected void onResume() {
 69         super.onResume();
 70         SurfaceHolder surfaceHolder = surfaceView.getHolder();
 71         if (hasSurface) {
 72             initCamera(surfaceHolder);
 73         } else {
 74             surfaceHolder.addCallback(this);
 75             surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
 76         }
 77         decodeFormats = null;
 78         characterSet = null;
 79 
 80         playBeep = true;
 81         AudioManager audioService = (AudioManager) getSystemService(AUDIO_SERVICE);
 82         if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
 83             playBeep = false;
 84         }
 85         initBeepSound();
 86         vibrate = true;
 87     }
 88 
 89     @Override
 90     protected void onPause() {
 91         super.onPause();
 92         if (handler != null) {
 93             handler.quitSynchronously();
 94             handler = null;
 95         }
 96         CameraManager.get().closeDriver();
 97     }
 98 
 99     @Override
100     protected void onDestroy() {
101         inactivityTimer.shutdown();
102         super.onDestroy();
103     }
104 
105 
106     public static final String RESULT_QRCODE_STRING = "RESULT_QRCODE_STRING";
107     /**
108      * Handler scan result
109      * @param result
110      * @param barcode
111      */
112     public void handleDecode(Result result, Bitmap barcode) {
113         inactivityTimer.onActivity();
114         playBeepSoundAndVibrate();
115         String resultString = result.getText();
116         //FIXME
117         if (resultString.equals("")) {
118             Toast.makeText(CaptureActivity.this, "Scan failed!", Toast.LENGTH_SHORT).show();
119         }
120 
121         setResult(RESULT_OK, new Intent().putExtra(RESULT_QRCODE_STRING, resultString));
122         finish();
123     }
124 
125     private void initCamera(SurfaceHolder surfaceHolder) {
126         try {
127             CameraManager.get().openDriver(surfaceHolder);
128         } catch (IOException ioe) {
129             return;
130         } catch (RuntimeException e) {
131             return;
132         }
133         if (handler == null) {
134             handler = new CaptureActivityHandler(this, decodeFormats,
135                     characterSet, viewfinderView, this);
136         }
137     }
138 
139     @Override
140     public void drawViewfinder() {
141         viewfinderView.drawViewfinder();        
142     }
143 
144 
145     @Override
146     public void surfaceChanged(SurfaceHolder holder, int format, int width,
147             int height) {
148 
149     }
150 
151     @Override
152     public void surfaceCreated(SurfaceHolder holder) {
153         if (!hasSurface) {
154             hasSurface = true;
155             initCamera(holder);
156         }
157 
158     }
159 
160     @Override
161     public void surfaceDestroyed(SurfaceHolder holder) {
162         hasSurface = false;
163 
164     }
165 
166 
167     public Handler getHandler() {
168         return handler;
169     }
170 
171 
172     private void initBeepSound() {
173         if (playBeep && mediaPlayer == null) {
174             // The volume on STREAM_SYSTEM is not adjustable, and users found it
175             // too loud,
176             // so we now play on the music stream.
177             setVolumeControlStream(AudioManager.STREAM_MUSIC);
178             mediaPlayer = new MediaPlayer();
179             mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
180             mediaPlayer.setOnCompletionListener(beepListener);
181 
182             AssetFileDescriptor file = getResources().openRawResourceFd(
183                     R.raw.beep);
184             try {
185                 mediaPlayer.setDataSource(file.getFileDescriptor(),
186                         file.getStartOffset(), file.getLength());
187                 file.close();
188                 mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
189                 mediaPlayer.prepare();
190             } catch (IOException e) {
191                 mediaPlayer = null;
192             }
193         }
194     }
195 
196     private static final long VIBRATE_DURATION = 200L;
197 
198     private void playBeepSoundAndVibrate() {
199         if (playBeep && mediaPlayer != null) {
200             mediaPlayer.start();
201         }
202         if (vibrate) {
203             Vibrator vibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
204             vibrator.vibrate(VIBRATE_DURATION);
205         }
206     }
207 
208     /**
209      * When the beep has finished playing, rewind to queue up another one.
210      */
211     private final OnCompletionListener beepListener = new OnCompletionListener() {
212         public void onCompletion(MediaPlayer mediaPlayer) {
213             mediaPlayer.seekTo(0);
214         }
215     };
216 
217 }

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

CameraScanActivity.java

  1 package zuo.biao.activity;
  2 
  3 import zuo.biao.R;
  4 import zuo.biao.library.interfaces.OnBottomDragListener;
  5 import zuo.biao.util.ActivityUtil;
  6 import android.content.Context;
  7 import android.content.Intent;
  8 import android.os.Bundle;
  9 import android.view.SurfaceHolder.Callback;
 10 import android.view.SurfaceView;
 11 import android.view.View;
 12 import android.view.View.OnClickListener;
 13 
 14 import com.zxing.activity.CaptureActivity;
 15 import com.zxing.camera.CameraManager;
 16 import com.zxing.view.ViewfinderView;
 17 
 18 /**扫描二维码Activity
 19  * @author Lemon
 20  * @use 参考zuo.biao.library.ModelActivity
 21  */
 22 public class CameraScanActivity extends CaptureActivity implements Callback, OnClickListener, OnBottomDragListener {
 23     public static final String TAG = "CameraScanActivity";
 24 
 25     //启动方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 26 
 27     /**启动这个Activity的Intent
 28      * @param context
 29      * @param title
 30      * @return
 31      */
 32     public static Intent createIntent(Context context) {
 33         return new Intent(context, CameraScanActivity.class);
 34     }
 35 
 36     //启动方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 37 
 38 
 39 
 40     @Override
 41     protected void onCreate(Bundle savedInstanceState) {
 42         super.onCreate(savedInstanceState);
 43         setContentView(R.layout.camera_scan_activity);
 44         init(this, (SurfaceView) findViewById(R.id.svCameraScan), (ViewfinderView) findViewById(R.id.vfvCameraScan));
 45 
 46         //功能归类分区方法,必须调用<<<<<<<<<<
 47         initView();
 48         initData();
 49         initListener();
 50         //功能归类分区方法,必须调用>>>>>>>>>>
 51 
 52     }
 53 
 54 
 55     //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 56 
 57     public void initView() {//必须调用
 58 
 59     }
 60 
 61 
 62 
 63     //UI显示区(操作UI,但不存在数据获取或处理代码,也不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 64 
 65 
 66 
 67 
 68 
 69 
 70 
 71 
 72 
 73 
 74     //data数据区(存在数据获取或处理代码,但不存在事件监听代码)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 75 
 76     public void initData() {//必须调用
 77 
 78     }
 79 
 80 
 81     //data数据区(存在数据获取或处理代码,但不存在事件监听代码)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 82 
 83 
 84 
 85 
 86 
 87 
 88 
 89 
 90     //listener事件监听区(只要存在事件监听代码就是)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
 91 
 92     public void initListener() {//必须调用
 93 
 94         findViewById(R.id.tvCameraScanReturn).setOnClickListener(this);
 95         findViewById(R.id.ivCameraScanReturn).setOnClickListener(this);
 96         findViewById(R.id.ivCameraScanLight).setOnClickListener(this);
 97         findViewById(R.id.ivCameraScanMyQRCode).setOnClickListener(this);
 98     }
 99 
100     //系统自带监听方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
101 
102     @Override
103     public void onDragBottom(boolean rightToLeft) {
104         if (rightToLeft) {
105 
106             return;
107         }
108 
109         finish();
110     }
111 
112     @Override
113     public void onClick(View v) {
114         switch (v.getId()) {
115         case R.id.tvCameraScanReturn:
116         case R.id.ivCameraScanReturn:
117             onDragBottom(false);
118             break;
119         case R.id.ivCameraScanLight:
120             switchLight(! isOpen);
121             break;
122         case R.id.ivCameraScanMyQRCode:
123             //
124             break;
125         default:
126             break;
127         }
128     }
129 
130 
131     private boolean isOpen = false;
132     /**打开或关闭闪关灯
133      * @param open
134      */
135     private void switchLight(boolean open) {
136         if (open == isOpen) {
137             return;
138         }
139         isOpen = CameraManager.get().switchLight(open);
140     }
141 
142 
143     //类相关监听<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
144 
145 
146     //类相关监听>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
147 
148     //系统自带监听方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
149 
150 
151     //listener事件监听区(只要存在事件监听代码就是)>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
152 
153 
154 
155 
156 
157 
158 
159 
160     //内部类,尽量少用<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
161 
162 
163 
164     //内部类,尽量少用>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
165 
166 }

 

CameraScanActivity布局文件camera_scan_activity.xml

  1 <?xml version="1.0" encoding="utf-8"?>
  2 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3     style="@style/activity_page" >
  4 
  5     <SurfaceView
  6         android:id="@+id/svCameraScan"
  7         android:layout_width="wrap_content"
  8         android:layout_height="wrap_content"
  9         android:layout_gravity="center" />
 10 
 11     <!-- 必须在最底层,且不能指定宽高,否则扫描读取很难实现 -->
 12     <com.zxing.view.ViewfinderView
 13         android:id="@+id/vfvCameraScan"
 14         android:layout_width="match_parent"
 15         android:layout_height="match_parent" />
 16 
 17     <LinearLayout
 18         style="@style/ll_vertical_match_match"
 19         android:baselineAligned="false" >
 20 
 21         <RelativeLayout
 22             style="@style/topbar_bg"
 23             android:background="@color/white_alpha" >
 24 
 25             <TextView
 26                 android:id="@+id/tvCameraScanReturn"
 27                 style="@style/topbar_left_btn"
 28                 android:text="          " />
 29 
 30             <TextView
 31                 style="@style/topbar_title"
 32                 android:layout_centerHorizontal="true"
 33                 android:text="扫一扫" />
 34         </RelativeLayout>
 35 
 36         <LinearLayout
 37             style="@style/ll_vertical_match_match"
 38             android:layout_gravity="center_horizontal"
 39             android:layout_weight="1" >
 40 
 41             <TextView
 42                 style="@style/text_middle_white"
 43                 android:layout_margin="30dp"
 44                 android:text="@string/camera_scan_remind" />
 45         </LinearLayout>
 46 
 47         <LinearLayout
 48             style="@style/ll_horizontal_match_wrap"
 49             android:layout_gravity="bottom"
 50             android:background="@color/white_alpha"
 51             android:gravity="center" >
 52 
 53             <LinearLayout
 54                 style="@style/ll_vertical_wrap_wrap"
 55                 android:layout_margin="12dp"
 56                 android:paddingBottom="4dp"
 57                 android:paddingLeft="12dp"
 58                 android:paddingRight="12dp"
 59                 android:paddingTop="4dp" >
 60 
 61                 <ImageView
 62                     android:id="@+id/ivCameraScanReturn"
 63                     style="@style/wrap_wrap"
 64                     android:background="@drawable/cilcle_gray_to_white"
 65                     android:padding="12dp"
 66                     android:src="@drawable/back_black_light" />
 67 
 68                 <TextView
 69                     style="@style/text_small"
 70                     android:layout_marginTop="4dp"
 71                     android:text="返回" />
 72             </LinearLayout>
 73 
 74             <LinearLayout
 75                 style="@style/ll_vertical_wrap_wrap"
 76                 android:layout_margin="12dp"
 77                 android:paddingBottom="4dp"
 78                 android:paddingLeft="12dp"
 79                 android:paddingRight="12dp"
 80                 android:paddingTop="4dp" >
 81 
 82                 <ImageView
 83                     android:id="@+id/ivCameraScanLight"
 84                     style="@style/wrap_wrap"
 85                     android:background="@drawable/cilcle_gray_to_white"
 86                     android:padding="12dp"
 87                     android:src="@drawable/flash_light" />
 88 
 89                 <TextView
 90                     style="@style/text_small"
 91                     android:layout_marginTop="4dp"
 92                     android:text="开灯/关灯" />
 93             </LinearLayout>
 94 
 95             <LinearLayout
 96                 style="@style/ll_vertical_wrap_wrap"
 97                 android:layout_margin="12dp"
 98                 android:paddingBottom="4dp"
 99                 android:paddingLeft="12dp"
100                 android:paddingRight="12dp"
101                 android:paddingTop="4dp" >
102 
103                 <ImageView
104                     android:id="@+id/ivCameraScanMyQRCode"
105                     style="@style/wrap_wrap"
106                     android:background="@drawable/cilcle_gray_to_white"
107                     android:padding="12dp"
108                     android:src="@drawable/qrcode" />
109 
110                 <TextView
111                     style="@style/text_small"
112                     android:layout_marginTop="4dp"
113                     android:text="我的名片" />
114             </LinearLayout>
115         </LinearLayout>
116     </LinearLayout>
117 
118 </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 

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

 

发表评论
用户名: 匿名