項(xiàng)目 QRCodeFlutterPlugin
一個(gè)非常方便實(shí)用的二維碼掃描、解析庫(kù),包含flutter端統(tǒng)一繪制頁(yè)面,也包含native端各自繪制頁(yè)面的實(shí)現(xiàn)方式膏蚓。
項(xiàng)目demo apk
項(xiàng)目源碼
已實(shí)現(xiàn)功能
- flutter 端統(tǒng)一繪制頁(yè)面,相機(jī)和本地相冊(cè)識(shí)別的二維碼
- native端單獨(dú)繪制的頁(yè)面畸写,實(shí)現(xiàn)的相機(jī)識(shí)別二維碼
- native端單自定義樣式的頁(yè)面驮瞧,實(shí)現(xiàn)的相機(jī)識(shí)別二維碼
- native 本地圖片二維碼識(shí)別
TODO
- 二維碼生成
- 二維碼帶logo生成
- 條形碼生成
- 條形碼識(shí)別包含本地圖片和相機(jī)識(shí)別
- iOS端實(shí)現(xiàn)
一 flutter 端統(tǒng)一實(shí)現(xiàn)的頁(yè)面:
使用flutter PlatformView去實(shí)現(xiàn),Android 端AndroidView枯芬,iOS端UiKitView论笔。這種view方式實(shí)現(xiàn)可以參考網(wǎng)上的實(shí)現(xiàn)方式。
使用該方式實(shí)現(xiàn)需要用戶手動(dòng)處理相機(jī)的生命周期破停,因此需要在flutter端監(jiān)聽(tīng)對(duì)應(yīng)的方法翅楼,可以通過(guò)混入方式with WidgetsBindingObserver實(shí)現(xiàn),重寫didChangeAppLifecycleState方法真慢,代碼如下:
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.inactive: //前后臺(tái)切換都執(zhí)行
break;
case AppLifecycleState.paused: //前臺(tái)到后臺(tái)
//需處理onPaused需知執(zhí)行的毅臊,即相機(jī)資源釋放
_scanViewController.closeAutoFlash();
setState(() {
_clickBool = !_clickBool;
});
if (ModalRoute.of(context).isCurrent) {
_scanViewController.stopScan();
}
break;
case AppLifecycleState.resumed: //后臺(tái)到前臺(tái)
//需處理onResumed需知執(zhí)行的,即相機(jī)資源重新獲取
if (ModalRoute.of(context).isCurrent) {
_scanViewController.restartScan();
}
break;
case AppLifecycleState.suspending:
break;
}
super.didChangeAppLifecycleState(state);
}
二 native端實(shí)現(xiàn)的頁(yè)面:
- 默認(rèn)二維碼掃描界面CaptureActivity
二維碼的掃描結(jié)果通過(guò)Intent返回出來(lái):
XQRCode.RESULT_TYPE:掃描結(jié)果類型黑界,XQRCode.RESULT_SUCCESS代表掃描成功管嬉,XQRCode.RESULT_FAILED代表掃描失敗。
XQRCode.RESULT_DATA:掃描二維碼的數(shù)據(jù)內(nèi)容朗鸠。
Activity activity = (Activity) mContext;
Intent intent = new Intent(activity, CaptureActivity.class);
intent.putExtra(KEY_CAPTURE_THEME, R.style.XQRCodeTheme);
activity.startActivityForResult(intent, REQUEST_CODE);
/**
* 處理二維碼掃描結(jié)果
* @param data
*/
private void handleScanResult(Intent data) {
if (data != null) {
Bundle bundle = data.getExtras();
if (bundle != null) {
if (bundle.getInt(XQRCode.RESULT_TYPE) == XQRCode.RESULT_SUCCESS) {
String result = bundle.getString(XQRCode.RESULT_DATA);
ToastUtils.toast("解析結(jié)果:" + result, Toast.LENGTH_LONG);
} else if (bundle.getInt(XQRCode.RESULT_TYPE) == XQRCode.RESULT_FAILED) {
ToastUtils.toast("解析二維碼失敗", Toast.LENGTH_LONG);
}
}
}
}
- 自定義二維碼掃描界面
(1)自定義一個(gè)掃碼界面布局蚯撩。自定義的掃碼界面需要定義一個(gè)SurfaceView和一個(gè)ViewfinderView,且id必須是preview_view和viewfinder_view烛占。詳情見(jiàn)如下布局代碼:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SurfaceView
android:id="@+id/preview_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<flutterqrcode.lizaihao.qr_code_flutter_plugin.view.ViewfinderView
android:id="@+id/viewfinder_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:inner_corner_color="@color/scan_corner_color"
app:inner_corner_length="30dp"
app:inner_corner_width="5dp"
app:inner_marginTop="120dp"
app:inner_scan_bitmap="@mipmap/ic_scan_image"
app:inner_scan_isCircle="false"
app:inner_scan_speed="10"
app:inner_height="300dp"
app:inner_width="300dp" />
</FrameLayout>
(2)調(diào)用XQRCode.getCaptureFragment的方法胎挎,傳入自定義掃描界面的布局ID沟启,可以獲得帶掃描功能的Fragment-CaptureFragment,將其填充到頁(yè)面中犹菇。
// 為二維碼掃描界面設(shè)置定制化界面
CaptureFragment captureFragment = XQRCode.getCaptureFragment(R.layout.layout_custom_camera);
captureFragment.setAnalyzeCallback(analyzeCallback);
getChildFragmentManager().beginTransaction().replace(R.id.fl_my_container, captureFragment).commit();
(3)最后為CaptureFragment設(shè)置二維碼解析回調(diào)接口AnalyzeCallback即可德迹。
2.1、二維碼解析
只需要解析二維碼攜帶的數(shù)據(jù)內(nèi)容揭芍,可直接調(diào)用XQRCode.analyzeQRCode方法胳搞,傳入二維碼的絕對(duì)路徑即可。
-
如果需要完整的二維碼解析結(jié)果称杨,可調(diào)用XQRCode.getAnalyzeQRCodeResult方法肌毅,傳入二維碼的絕對(duì)路徑即可。
native端實(shí)現(xiàn)的頁(yè)面