Android項(xiàng)目實(shí)戰(zhàn)(二十八):使用Zxing實(shí)現(xiàn)二維碼及優(yōu)化實(shí)例
前言:
多年之前接觸過(guò)zxing實(shí)現(xiàn)二維碼,沒(méi)想到今日項(xiàng)目中再此使用竟然使用的還是zxing,百度之,竟是如此牛的玩意。
當(dāng)然,項(xiàng)目中我們也許只會(huì)用到二維碼的掃描和生成兩個(gè)功能,所以不必下載完整的jar包,使用簡(jiǎn)化版的即可,下文可見(jiàn)。
這篇文章講述:
1、如果快速在項(xiàng)目中集成zxing,實(shí)現(xiàn)掃描和生成二維碼功能
2、根據(jù)項(xiàng)目需求去修改源碼實(shí)現(xiàn)我們的要求并進(jìn)行優(yōu)化
一、快速集成zxing二維碼
1、下載庫(kù)文件 :http://xiazai.jb51.net/201611/yuanma/ZXingBarCode_jb51.zip ,
下載完成后可以看到:
我們從這些文件中拷貝需要的到自己的項(xiàng)目中,下面開(kāi)始:
?、?、res 目錄下 : raw文件夾 整個(gè)復(fù)制到個(gè)人項(xiàng)目相對(duì)位置
?、?、res --> values目錄下:ids.xml文件中的內(nèi)容全部復(fù)制到個(gè)人項(xiàng)目相對(duì)位置,個(gè)人項(xiàng)目沒(méi)有則直接復(fù)制文件到相對(duì)位置
③、res --> values目錄下:colors.xml文件中的內(nèi)容全部復(fù)制到個(gè)人項(xiàng)目的相對(duì)位置
④、res --> layout目錄下:camera.xml 布局文件復(fù)制到個(gè)人項(xiàng)目相對(duì)位置
?、荨es --> drawable_mdpi 目錄下:navbar.9.png圖片復(fù)制到個(gè)人項(xiàng)目相對(duì)位置,這張圖片是標(biāo)題欄背景圖片,這里建議先改成navbar.png 不要使用.9圖片
?、蕖ibs目錄下:zxing.jar文件復(fù)制到個(gè)人項(xiàng)目相對(duì)位置,并且右鍵點(diǎn)擊as library
?、摺rc --> com目錄下:zxing 文件夾復(fù)制到個(gè)人項(xiàng)目相對(duì)位置 ,會(huì)報(bào)錯(cuò),修改R的目錄結(jié)構(gòu)即可
?、?、AndroidManifest.xml文件中 添加 (二維碼掃描activity,這個(gè)需要后面自己去修改,用于實(shí)現(xiàn)自己的要求)
<activity android:name="com.zxing.activity.CaptureActivity"/>
⑨、AndroidManifest.xml文件中 添加權(quán)限
<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2、準(zhǔn)備工作完成了,下面開(kāi)始寫(xiě)demo
現(xiàn)在需求是一個(gè)主界面MainActivity.java 里面有兩個(gè)按鈕,分別跳轉(zhuǎn) 生成二維碼界面和 掃描二維碼界面
然后分別開(kāi)始寫(xiě)兩個(gè)activity功能的實(shí)現(xiàn):
①、 生成二維碼
先寫(xiě)布局文件 ,一個(gè)圖片 , 一個(gè)開(kāi)始生成按鈕 , 一個(gè)輸入框(二維碼需要根據(jù)文本信息生成,沒(méi)有文本信息無(wú)法生成)
activity_create.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.maiji.zxingdemo.CreateActivity"> <ImageView android:id="@+id/create_img" android:layout_width="300dp" android:layout_height="300dp" android:scaleType="fitXY" android:layout_gravity="center_horizontal" /> <Button android:id="@+id/create_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="開(kāi)始生成二維碼" /> <EditText android:id="@+id/create_edit" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
activity代碼: 代碼比較簡(jiǎn)單 ,不在此解釋了
private ImageView create_img; private Button create_btn; private EditText create_edit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_create); initView(); initEvent(); } private void initEvent() { create_btn.setOnClickListener(this); } private void initView() { create_img = (ImageView) findViewById(R.id.create_img); create_btn = (Button) findViewById(R.id.create_btn); create_edit = (EditText) findViewById(R.id.create_edit); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.create_btn: String content = "" ; if (create_edit.getText().toString().equals("")){ Toast.makeText(this,"請(qǐng)輸入二維碼信息",Toast.LENGTH_SHORT).show(); return; } content = create_edit.getText().toString(); try { //生成二維碼圖片,第一個(gè)參數(shù)是二維碼的內(nèi)容,第二個(gè)參數(shù)是正方形圖片的邊長(zhǎng),單位是像素 Bitmap qrcodeBitmap = EncodingHandler.createQRCode(content, 800); if (qrcodeBitmap!=null) { create_img.setImageBitmap(qrcodeBitmap); }else{ Toast.makeText(this,"生成二維碼失敗",Toast.LENGTH_SHORT).show(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } break; } } public byte[] Bitmap2Bytes(Bitmap bm) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); bm.compress(Bitmap.CompressFormat.PNG, 100, baos); return baos.toByteArray(); }
效果圖:
②、掃描二維碼
這個(gè)就更簡(jiǎn)單了,只需要打開(kāi)一個(gè)zxing提供的activity 然后獲取到掃描得到的字符串即可
看ScanActivity(掃描Activity)的關(guān)鍵代碼
private TextView zxing_content; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_scan); zxing_content = (TextView) findViewById(R.id.zxing_content); Intent startScan = new Intent(this,CaptureActivity.class); startActivityForResult(startScan, 0); //實(shí)際打開(kāi)了一個(gè)zxing提供給我們的掃描activity,當(dāng)然我們后面會(huì)對(duì)這個(gè)activity進(jìn)行一些優(yōu)化修改 } /** * 掃一掃,成功后返回值進(jìn)行判斷 */ @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == -1) { String result = data.getExtras().getString("result"); zxing_content.setText(result); //顯示掃描二維碼得到的數(shù)據(jù) } }
布局文件:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.maiji.zxingdemo.ScanActivity"> <TextView android:id="@+id/zxing_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textSize="30sp" /> </RelativeLayout>
效果圖:
二、修改源碼,實(shí)現(xiàn)項(xiàng)目的需求
1、修改掃描二維碼的界面
對(duì)應(yīng)的是 zxing-->activity-->CaptureActivity.java ,布局文件為 camera.xml
所以修改界面只需要在 camera.xml文件中修改即可。
無(wú)非就是把原來(lái)的“CANCEL”取消按鈕去掉,把頂部的標(biāo)題欄換一下。
布局里面有一個(gè) <SurfaceView>控件 用于顯示相機(jī)拍出的畫(huà)面預(yù)覽,這里可以根據(jù)需求改是全界面顯示還是顯示局部
<com.zxing.view.ViewfinderView>控件,即掃描框,默認(rèn)的是寬高比1:1.5,實(shí)際需要修改寬高,在下面介紹
2、修改掃描框的寬高
第1步操作做完之后會(huì)發(fā)現(xiàn),我們沒(méi)法修改掃描框的寬高。
修改掃描框?qū)捀吆芎?jiǎn)單,找到 zxing-->camera-->CameraManager.java 文件
這里較為頂部的代碼中看到:
private static final int MIN_FRAME_WIDTH = 240; private static final int MIN_FRAME_HEIGHT = 240; private static final int MAX_FRAME_WIDTH = 480; private static final int MAX_FRAME_HEIGHT = 480;
這四個(gè)屬性的值即掃描框的寬高,然后可以根據(jù)需求直接修改,當(dāng)然這個(gè)值在不同分辨率的設(shè)備上寬高不一致 , 有需要的話(huà)可以進(jìn)行一下單位轉(zhuǎn)換
public static int Dp2Px( Context context,float dp) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dp * scale + 0.5f); }
效果圖: 我修改了掃描框的最小最大寬高分別一致,并且載camera.xml布局中刪去了“CANCEL”取消按鈕
3、給掃描框添加文字提示
看一下微信的掃描界面,會(huì)發(fā)現(xiàn)掃描框下面有一段文字提示。 那么我們這里沒(méi)有,需要添加
找到zxing-->view-->Viewfinderview.java
這里是自定義掃描框的類(lèi)
找到代碼:
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint); Collection<ResultPoint> currentPossible = possibleResultPoints;
在這兩行代碼之間我們畫(huà)上文字提示
canvas.drawRect(frame.left + 2, middle - 1, frame.right - 1, middle + 2, paint); TextPaint textPaint = new TextPaint(); textPaint.setARGB(0xFF, 0xFF, 0xFF,0xFF); //字體顏色 textPaint.setTextSize(32); //字體大小 textPaint.setAntiAlias(true); //設(shè)置抗鋸齒,否則字跡會(huì)很模糊 StaticLayout layout = new StaticLayout("將二維碼放入框內(nèi),即可自動(dòng)掃描",textPaint, frame.right-frame.left, Layout.Alignment.ALIGN_NORMAL,1.0F,0.0F,true); canvas.translate(frame.left+5, (float) (frame.bottom + (float)30)); //繪制起始位置 layout.draw(canvas); Collection<ResultPoint> currentPossible = possibleResultPoints;
然后在看下掃描界面效果圖:
4、解決掃描界面相機(jī)預(yù)覽拉伸變形問(wèn)題
實(shí)現(xiàn)了上面幾步的優(yōu)化,仔細(xì)的同學(xué)可能會(huì)發(fā)現(xiàn),如果我們給SurfaceView設(shè)置全屏顯示(可以看到的相機(jī)畫(huà)面很多),會(huì)發(fā)現(xiàn)相機(jī)拍攝出來(lái)的預(yù)覽圖有些拉伸變形
原因:zxing橫屏變豎屏之后,Camera的代碼還是采用的橫屏代碼設(shè)置的參數(shù)
優(yōu)化方法:找到 zxing-->camera--> CameraConfigurationManager.java
initFromCameraParameters方法中,在 Log.d(TAG, "Screen resolution: " + screenResolution);這句之后增加 Point screenResolutionForCamera = new Point(); screenResolutionForCamera.x = screenResolution.x; screenResolutionForCamera.y = screenResolution.y; if (screenResolution.x < screenResolution.y) { screenResolutionForCamera.x = screenResolution.y; screenResolutionForCamera.y = screenResolution.x; }
再將cameraResolution = getCameraResolution(parameters, screenResolution);更改為
cameraResolution = getCameraResolution(parameters, screenResolutionForCamera);
完成之后,在進(jìn)行掃描操作,這時(shí)候相機(jī)拍出來(lái)的預(yù)覽界面就正常顯示,不再有拉伸變形問(wèn)題。
至此便給項(xiàng)目引入了一個(gè)可以使用的二維碼模塊功能了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Android實(shí)現(xiàn)雷達(dá)View效果的示例代碼
這篇文章主要介紹了Android實(shí)現(xiàn)雷達(dá)View效果,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06Android Studio設(shè)置主題與字體大小圖文教程
這篇文章通過(guò)圖文詳細(xì)的給大家介紹了Android Studio中如何設(shè)置主題與字體大小,文章介紹的非常詳細(xì),相信對(duì)大家學(xué)習(xí)使用Android Studio具有一定的參考借鑒價(jià)值,有需要的朋友們下面來(lái)一起看看吧。2016-10-10Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng)
滑動(dòng)刪除的部分主要包含兩個(gè)部分, 一個(gè)是內(nèi)容區(qū)域(用于放置正常顯示的view),另一個(gè)是操作區(qū)域(用于放置刪除按鈕)。下面通過(guò)本文給大家介紹Android 實(shí)現(xiàn)左滑出現(xiàn)刪除選項(xiàng),需要的朋友可以參考下2017-06-06Android實(shí)現(xiàn)后臺(tái)服務(wù)拍照功能
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)后臺(tái)服務(wù)拍照功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-05-05Android 實(shí)現(xiàn)不同字體顏色的TextView實(shí)現(xiàn)代碼
這篇文章主要介紹了Android 實(shí)現(xiàn)不同字體顏色的TextView實(shí)現(xiàn)代碼的相關(guān)資料,需要的朋友可以參考下2017-05-05玩轉(zhuǎn)Kotlin 徹底弄懂Lambda和高階函數(shù)
這篇文章主要幫助大家徹底弄懂Lambda和高階函數(shù),玩轉(zhuǎn)Kotlin,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10Android實(shí)現(xiàn)文字上下滾動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)文字上下滾動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-12-12Android?藍(lán)牙BLE開(kāi)發(fā)完全指南
BLE藍(lán)牙的興起主要因?yàn)榻陙?lái)可穿戴設(shè)備的流行,由于傳統(tǒng)藍(lán)牙功耗高不能滿(mǎn)足可穿戴設(shè)備對(duì)于續(xù)航的要求,所以大部分可穿戴設(shè)備采用藍(lán)牙4.0,即BLE藍(lán)牙技術(shù),這篇文章主要給大家介紹了關(guān)于Android?藍(lán)牙BLE開(kāi)發(fā)的相關(guān)資料,需要的朋友可以參考下2021-11-11