用到插件
flutter_qr_reader // 扫码
image_picker // 图片选择
permission_handler // 权限控制
# 扫码
flutter_qr_reader: ^1.0.5
# 动态鉴权
permission_handler: ^7.1.0
# 图片获取
image_picker: ^0.7.4
#flutter_picker: ^2.0.1
android配置 在/android/src/main/AndroidManifest.xml中
<uses-permission android:name="android.permission.CAMERA" /> <!-- 相机 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <!-- 存储权限 -->
IOS配置 在Info.plist中
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSAppleMusicUsageDescription</key>
<string>App需要您的同意,才能访问媒体资料库</string>
<key>NSCameraUsageDescription</key>
<string>App需要您的同意,才能访问相机</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>App需要您的同意,才能访问相册</string>
限 -->
scanPage.dart
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_qr_reader/flutter_qr_reader.dart';
import 'package:image_picker/image_picker.dart';
import 'package:permission_handler/permission_handler.dart';
class ScanPage extends StatefulWidget {
@override
_ScanPageState createState() => _ScanPageState();
}
class _ScanPageState extends State<ScanPage> {
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
bool flashlightState = false;
bool showScanView = false;
bool _openAction = false;
QrReaderViewController _controller;
Widget mainUi = Container();
@override
void initState() {
super.initState();
Future.delayed(Duration(milliseconds: 0)).then((_) async {
if (false == await permission()) {
// openAppSettings();
// Navigator.pop(context);
return;
}
setState(() {
mainUi = getScanUI();
});
});
}
// 扫码界面
Widget getScanUI() {
return Container(
child: Stack(
children: [
QrReaderView(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
callback: (controller) {
setState(() {
_controller = controller;
this.startScan();
});
},
),
Container(
height: 30,
padding: EdgeInsets.symmetric(horizontal: 30),
margin: EdgeInsets.only(top: MediaQuery.of(context).padding.top + 20),
// color: Colors.red,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: () {
Navigator.pop(context);
},
child: ClipOval(
child: Container(
width: 24,
height: 24,
color: Color.fromRGBO(0, 34, 51, 0.25),
child: Icon(Icons.clear, color: Colors.white, size: 18),
),
),
),
InkWell(
onTap: imgScan,
child: Image.asset('assets/images/img_img.png', width: 24),
),
],
),
),
Align(
child: Container(
height: MediaQuery.of(context).size.height * 0.8,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.width * 0.65,
width: MediaQuery.of(context).size.width * 0.65,
// decoration: BoxDecoration(border: Border.all(width: 1, color: Colors.redAccent)),
child: Image.asset('assets/images/scan_frame.png', fit: BoxFit.fitWidth),
),
Container(
margin: EdgeInsets.only(top: 30),
child: InkWell(
onTap: flashlight,
child: Image.asset('assets/images/icon_light.png', width: 17),
),
)
],
),
),
),
],
),
);
}
void alert(String tip) {
ScaffoldMessenger.of(scaffoldKey.currentContext).showSnackBar(SnackBar(content: Text(tip)));
}
// 相机权限dialog
void showJurisdictionDialog(String text) {
showDialog(
context: context,
builder: (ctx) {
return AlertDialog(
title: Text('提示'),
// content: Text('相机权限没有打开,是否去打开相机权限?'),
content: Text(text),
actions: <Widget>[
TextButton(
child: Text('取消'),
onPressed: () {
Navigator.pop(context);
},
),
TextButton(
child: Text('确认'),
onPressed: () {
openAppSettings(); // 打开权限设置
},
),
],
);
});
}
Future<bool> permission() async {
if (_openAction) return false;
_openAction = true;
var status = await Permission.camera.status;
// print(status);
if (status.isDenied || status.isPermanentlyDenied) {
status = await Permission.camera.request();
// print(status);
}
if (status.isRestricted) {
// alert("请必须授权照相机权限");
showJurisdictionDialog("请必须授权照相机权限");
// await Future.delayed(Duration(seconds: 3));
openAppSettings();
_openAction = false;
return false;
}
if (!status.isGranted) {
// alert("请必须授权照相机权限");
showJurisdictionDialog("请必须授权照相机权限");
_openAction = false;
return false;
}
_openAction = false;
return true;
}
// 开始扫码
Future startScan() async {
assert(_controller != null);
_controller?.startCamera((String result, _) async {
await stopScan();
debugPrint(result);
Navigator.pop(context, result);
});
}
// 暂停扫码
Future stopScan() async {
assert(_controller != null);
await _controller?.stopCamera();
setState(() {
showScanView = false;
});
}
// 打开手电筒
Future flashlight() async {
assert(_controller != null);
final state = await _controller?.setFlashlight();
setState(() {
flashlightState = state ?? false;
});
}
// 选择图片扫码
Future imgScan() async {
if (flashlightState) {
final state = await _controller?.setFlashlight();
setState(() {
flashlightState = state ?? false;
});
}
var image = await ImagePicker().getImage(source: ImageSource.gallery);
if (image == null) return;
final result = await FlutterQrReader.imgScan(image.path);
debugPrint(result);
Navigator.pop(context, result);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: mainUi,
);
}
}
调用
// 扫一扫点击
void onScan() async {
var result = await Navigator.pushNamed(context, '/scanPage');
debugPrint('---扫码结果---$result');
}
图片资源
图一
图二
图三