基于Flutter實現(xiàn)掃描二維碼功能
在今天的移動開發(fā)中,二維碼掃描已經(jīng)成為了常見的功能之一。Flutter作為一款跨平臺的開發(fā)框架,提供了豐富的插件和功能,使得開發(fā)者可以輕松實現(xiàn)二維碼掃描以及圖像識別功能。本文將介紹如何在Flutter中通過結合 scan 插件、permission_handler 插件以及 image_picker 插件,實現(xiàn)二維碼掃描和從相冊選擇二維碼圖片的功能。
效果圖
1、相機掃描二維碼

2、相冊選擇二維碼并掃描

1、項目依賴
首先,我們需要在 pubspec.yaml 文件中添加以下依賴:
dependencies:
flutter:
sdk: flutter
scan: ^1.6.0 # 用于掃描二維碼
permission_handler: ^10.2.0 # 用于權限請求
image_picker: ^1.0.7 # 用于從相冊選擇圖片
這些插件的作用如下:
scan:提供二維碼掃描功能。
permission_handler:用于請求相機權限,確保用戶授權后才能使用相機進行二維碼掃描。
image_picker:允許從相冊選擇圖片,便于用戶上傳二維碼圖片進行識別。
2、配置權限
在 Android 平臺上,為了使用相機功能,需要在 AndroidManifest.xml 文件中添加必要的權限:
<uses-permission android:name="android.permission.CAMERA"/>
在 IOS平臺上修改 Info.plist 文件,打開 ios/Runner/Info.plist 文件,確保添加以下配置(iOS用虛擬機是調(diào)試不了的,實測打不開相機):
<key>NSCameraUsageDescription</key>
<string>需要訪問相機用于二維碼掃描</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>需要訪問相冊選擇圖片</string>
3、實現(xiàn)二維碼掃描功能
接下來,我們來看看如何實現(xiàn)二維碼掃描功能。我們需要創(chuàng)建一個主界面,在其中添加按鈕來請求相機權限,并進行二維碼掃描。
沒有二維碼的小伙伴可以查看上一篇文章:Flutter 生成二維碼
import 'package:flutter/material.dart';
import 'package:scan/scan.dart'; // 導入 scan 插件
import 'package:permission_handler/permission_handler.dart'; // 導入權限請求插件
import 'package:image_picker/image_picker.dart'; // 導入相冊選擇插件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: QRScannerScreen(),
);
}
}
class QRScannerScreen extends StatefulWidget {
@override
_QRScannerScreenState createState() => _QRScannerScreenState();
}
class _QRScannerScreenState extends State<QRScannerScreen> {
ScanController controller = ScanController(); // 創(chuàng)建掃描控制器
String qrcode = 'Unknown'; // 默認二維碼內(nèi)容
// 執(zhí)行二維碼掃描前請求權限
_requestPermissions() async {
var cameraStatus = await Permission.camera.request();
if (cameraStatus.isGranted) {
// 權限已授予,開始掃描
print("相機權限已授予,開始掃描");
// 點擊按鈕后跳轉(zhuǎn)到全屏掃描界面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QRScanPage(controller: controller)),
).then((result) {
controller.pause(); // 暫停掃描
// 掃描完成后獲取返回的二維碼數(shù)據(jù)并更新顯示
if (result != null) {
setState(() {
qrcode = result; // 更新二維碼內(nèi)容
});
}
});
} else {
// 權限被拒絕或未授權
print("相機權限未授予,請授權");
// 可以引導用戶去設置頁面
}
}
// 選擇相冊中的二維碼圖片
_selectImageFromGallery() async {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
String result = await Scan.parse(pickedFile.path) ?? ''; // 解析選中的圖片
setState(() {
qrcode = result; // 更新二維碼內(nèi)容
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('二維碼掃描器'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 顯示二維碼掃描結果
const Text(
'二維碼掃描結果:',
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
Text(
qrcode,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 30),
// 掃描按鈕
ElevatedButton(
onPressed: _requestPermissions, // 執(zhí)行權限請求
child: const Text('請求權限并開始掃描'),
),
const SizedBox(height: 30),
// 選擇相冊按鈕
ElevatedButton(
onPressed: _selectImageFromGallery, // 選擇相冊
child: const Text('從相冊選擇二維碼圖片'),
),
],
),
),
);
}
}代碼解釋
權限請求:我們通過 permission_handler 插件請求相機權限。用戶允許后才能進行二維碼掃描。
掃描功能:我們使用 ScanController 來控制掃描過程。點擊按鈕后,跳轉(zhuǎn)到全屏掃描頁面 QRScanPage,在該頁面,用戶可以通過相機掃描二維碼。
從相冊選擇圖片:我們利用 image_picker 插件允許用戶從相冊選擇圖片,并解析二維碼。
4、全屏掃描頁面
當用戶點擊掃描按鈕時,應用會進入一個全屏掃描頁面。在該頁面中,二維碼掃描功能全屏展示,并且添加了一個“選擇相冊”按鈕,讓用戶可以在掃描時直接選擇圖片。
class QRScanPage extends StatelessWidget {
final ScanController controller;
const QRScanPage({super.key, required this.controller});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('掃描二維碼')),
body: Stack(
alignment: Alignment.center,
children: [
// 使用 ScanView 進行全屏掃描
ScanView(
controller: controller,
scanAreaScale: 0.8, // 設置掃描區(qū)域占滿整個屏幕
scanLineColor: Colors.green.shade400, // 設置掃描線顏色
onCapture: (data) {
// 掃描到二維碼后,返回數(shù)據(jù)
controller.pause(); // 暫停掃描
Navigator.pop(context, data); // 返回掃描結果
},
),
// 在屏幕上添加選擇相冊按鈕
Positioned(
bottom: 100,
child: ElevatedButton(
onPressed: () async {
// 選擇相冊
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
String result = await Scan.parse(pickedFile.path) ?? ''; // 解析選中的圖片
Navigator.pop(context, result); // 返回二維碼結果
}
},
child: const Text(
'選擇相冊',
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
);
}
}代碼解釋
ScanView:提供掃描界面,支持自定義掃描區(qū)域和掃描線顏色。
onCapture:當掃描到二維碼時,會返回掃描結果并暫停掃描。
選擇相冊按鈕:點擊按鈕可以讓用戶從相冊選擇二維碼圖片進行解析。
完整demo
可以直接復制到新項目跑起來
import 'package:flutter/material.dart';
import 'package:scan/scan.dart'; // 導入 scan 插件
import 'package:permission_handler/permission_handler.dart'; // 導入權限請求插件
import 'package:image_picker/image_picker.dart'; // 導入相冊選擇插件
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: QRScannerScreen(),
);
}
}
class QRScannerScreen extends StatefulWidget {
@override
_QRScannerScreenState createState() => _QRScannerScreenState();
}
class _QRScannerScreenState extends State<QRScannerScreen> {
ScanController controller = ScanController(); // 創(chuàng)建掃描控制器
String qrcode = 'Unknown'; // 默認二維碼內(nèi)容
// 執(zhí)行二維碼掃描前請求權限
_requestPermissions() async {
var cameraStatus = await Permission.camera.request();
if (cameraStatus.isGranted) {
// 權限已授予,開始掃描
print("相機權限已授予,開始掃描");
// 點擊按鈕后跳轉(zhuǎn)到全屏掃描界面
Navigator.push(
context,
MaterialPageRoute(builder: (context) => QRScanPage(controller: controller)),
).then((result) {
controller.pause(); // 暫停掃描
// 掃描完成后獲取返回的二維碼數(shù)據(jù)并更新顯示
if (result != null) {
setState(() {
qrcode = result; // 更新二維碼內(nèi)容
});
}
});
} else {
// 權限被拒絕或未授權
print("相機權限未授予,請授權");
// 可以引導用戶去設置頁面
}
}
// 選擇相冊中的二維碼圖片
_selectImageFromGallery() async {
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
String result = await Scan.parse(pickedFile.path) ?? ''; // 解析選中的圖片
setState(() {
qrcode = result; // 更新二維碼內(nèi)容
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('二維碼掃描器'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
// 顯示二維碼掃描結果
const Text(
'二維碼掃描結果:',
style: TextStyle(fontSize: 18),
),
const SizedBox(height: 10),
Text(
qrcode,
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
),
const SizedBox(height: 30),
// 掃描按鈕
ElevatedButton(
onPressed: _requestPermissions, // 執(zhí)行權限請求
child: const Text('請求權限并開始掃描'),
),
const SizedBox(height: 30),
// 選擇相冊按鈕
ElevatedButton(
onPressed: _selectImageFromGallery, // 選擇相冊
child: const Text('從相冊選擇二維碼圖片'),
),
],
),
),
);
}
}
class QRScanPage extends StatelessWidget {
final ScanController controller;
const QRScanPage({super.key, required this.controller});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('掃描二維碼')),
body: Stack(
alignment: Alignment.center,
children: [
// 使用 ScanView 進行全屏掃描
ScanView(
controller: controller,
scanAreaScale: 0.8, // 設置掃描區(qū)域占滿整個屏幕
scanLineColor: Colors.green.shade400, // 設置掃描線顏色
onCapture: (data) {
// 掃描到二維碼后,返回數(shù)據(jù)
controller.pause(); // 暫停掃描
Navigator.pop(context, data); // 返回掃描結果
},
),
// 在屏幕上添加選擇相冊按鈕
Positioned(
bottom: 100,
child: ElevatedButton(
onPressed: () async {
// 選擇相冊
final picker = ImagePicker();
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
if (pickedFile != null) {
String result = await Scan.parse(pickedFile.path) ?? ''; // 解析選中的圖片
Navigator.pop(context, result); // 返回二維碼結果
}
},
child: const Text(
'選擇相冊',
style: TextStyle(
fontSize: 18,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
);
}
}總結
本文展示了如何在 Flutter 中實現(xiàn)二維碼掃描和從相冊選擇二維碼圖片的功能。通過使用 scan、permission_handler 和 image_picker 插件,我們可以輕松地添加二維碼掃描和圖片識別功能。在開發(fā)實際應用時,可能還需要處理更多細節(jié),例如處理不同平臺的權限請求、優(yōu)化掃描體驗等。
到此這篇關于基于Flutter實現(xiàn)掃描二維碼功能的文章就介紹到這了,更多相關Flutter掃描二維碼內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Android文本視圖TextView實現(xiàn)跑馬燈效果
這篇文章主要為大家詳細介紹了Android文本視圖TextView實現(xiàn)跑馬燈效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05
Android Messenger實現(xiàn)進程間通信及其原理
這篇文章主要為大家詳細介紹了Android Messenger實現(xiàn)進程間通信及其原理,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-05-05

