Let me show you the renderings first:
The scanned content is the one below, the QR code is generated using the zxing library
Since I have changed several classes, I have almost forgotten what happened last year, so I can only upload the code of this class. The main thing is to change this 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(); } }; }
Use Method: Create a new Activity that inherits CaptureActivity and calls the init method after the setContentView method.
Example:
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 layout file 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>
The layout file uses some styles, colors, etc. in ZBLibrary , there will be some errors if there is only this layout. Just create a new layout file yourself and put ViewfinderView in the outermost layout file. Of course, after downloading the source code attached below, there will be no problem.
By the way, remember to add these permissions in 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" />
Attached source code (including usage)
GitHub source code https://github.com/TommyLemon/Android-ZBLibrary
Open source Chinese source code http://git.oschina.net/Lemon19950301/Android-ZBLibrary
This is where I will introduce you to the custom ZXing QR code scanning interface of the Android development framework and solve the problem of stretching the viewfinder. The above content is a bit long. I hope you can read it patiently. If you have any questions, please leave me a message. The editor will reply to everyone in time. Thank you very much for your support of the PHP Chinese website!
For more related articles on customizing the ZXing QR code scanning interface of the Android development framework and solving the problem of stretching the viewfinder, please pay attention to the PHP Chinese website!