Flutter相机使用插件easy_use_camera的功能
Flutter相机使用插件easy_use_camera的功能
🌍 关于项目
本包用于在所有平台上使用相机拍摄照片和视频。
🛠 构建工具
- 相机插件: Camera
- SVG图片插件: Flutter SVG
源代码结构
/my_camera
example/
lib/
main.dart
lib/
camera/
dialog/
widget/
take_picture.dart
my_camera.dart
🧾 设置项目
Android
android {
...
defaultConfig {
minSdkVersion 21
}
}
iOS
<key>NSCameraUsageDescription</key>
<string>本应用需要访问相机</string>
<key>NSMicrophoneUsageDescription</key>
<string>本应用需要访问麦克风</string>
PWA
需要在主机上启用SSL。
命名规范
什么 | 如何 | 示例 |
---|---|---|
类、枚举、类型别名 | 大驼峰式命名 | ProductBloc |
库、包、目录、源文件名 | 下划线命名 | product_detail_view |
变量、常量、参数、命名参数 | 小驼峰式命名 | variants |
清洁代码
- 创建UIKit组件库用于常见组件
- 不直接使用颜色或字体样式,使用UIKit
- 将组件拆分为子组件
- 为每个功能创建组件包
- 明确指定类成员类型
- 使用if条件语句而不是条件表达式
- 使用??和?.操作符
- 使用级联操作符
// 不推荐 var path = Path(); path.lineTo(0, size.height); path.lineTo(size.width, size.height); path.lineTo(size.width, 0); path.close(); // 推荐 var path = Path() ..lineTo(0, size.height) ..lineTo(size.width, size.height) ..lineTo(size.width, 0) ..close();
- 在Widgets中使用Const
⛑ 代码审查
代码审查者关注的点
- 设计:代码是否设计良好且适合您的系统?
- 功能性:代码的行为是否符合作者的意图?代码的行为是否对用户友好?
- 复杂度:代码是否可以简化?其他开发人员在未来阅读和使用此代码时是否容易理解?
- 测试:代码是否有正确的自动化测试?
- 命名:开发人员是否选择了清晰的变量、类、方法等名称?
- 注释:注释是否清晰有用?
- 风格:代码是否遵循我们的编码风格指南?
- 文档:开发人员是否更新了相关的文档?
如何实施代码审查
- 每个合并请求(Pull Request)必须满足以下检查列表,以确保过程中没有出现任何问题。
- 检查分支是否未损坏
- 检查功能是否实现
- 检查测试用例是否通过
- 检查代码风格(使用lint或手动)
- 检查可读性
- 检查副作用
- 检查与其他类/包/模块的一致性
- 检查合并请求上的所有注释
- 审查者如果对合并请求有任何意见,可以在相应的行上留下评论。
📚 致谢
示例代码
example/lib/main.dart
import 'dart:io';
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:easy_use_camera/easy_use_camera.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// 这个小部件是你的应用的根。
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(title),
),
body: Column(
children: [
ElevatedButton(
onPressed: () async {
final result = await takeFaceVideoOnDialog(
context,
direction: CameraLensDirection.front,
resolutionPreset: ResolutionPreset.low,
scanWidget: Align(
alignment: Alignment.bottomCenter,
child: Container(
width: double.maxFinite,
height: 100,
decoration: BoxDecoration(
color: Colors.amber.withOpacity(0.3)
),
),
),
);
if (context.mounted && result != null) {
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => PreviewVideo(
rotateAngle: math.pi / 2,
file: result,
topFaceBuilder: (context) {
return Center(
child: Text("Hello"),
);
},
),
),
);
}
},
child: Text('录制视频', style: Theme.of(context).textTheme.bodySmall?.copyWith(color: Colors.black)),
),
ElevatedButton(
onPressed: () async {
final result = await takeFacePictureOnDialog(context);
if (result != null) {
File file = File(result.path);
print(file.path);
}
},
child: const Text('拍摄人脸照片'),
),
ElevatedButton(
onPressed: () async {
final result = await takeCardPictureOnDialog(context);
if (result != null) {
File file = File(result.path);
print(file.path);
}
},
child: const Text('拍摄卡片照片'),
),
ElevatedButton(
onPressed: () async {
final result = await takeDocumentPictureOnDialog(context);
if (result != null) {
File file = File(result.path);
print(file.path);
}
},
child: const Text('拍摄文档照片'),
),
],
),
);
}
}
更多关于Flutter相机使用插件easy_use_camera的功能的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复