flutter开发实战-自定义相机camera功能
flutter开发实战-自定义相机camera功能。
Flutter 本质上只是一个 UI 框架,运行在宿主平台之上,Flutter 本身是无法提供一些系统能力,比如使用蓝牙、相机、GPS等,因此要在 Flutter 中调用这些能力就必须和原生平台进行通信。
 实现相机功能,我们使用的是camera插件。
一、引入camera插件
在pubspec.yaml引入插件
  # Camera相机拍照等camera: ^0.10.5+2image: ^4.0.17
 
二、实现相机拍照功能
在iOS的info.plist文件增加相机、麦克风权限
<key>NSCameraUsageDescription</key>
<string>your usage description here</string>
<key>NSMicrophoneUsageDescription</key>
<string>your usage description here</string>
 
在Android的android/app/build.gradle调整
minSdkVersion 21
 
处理详情权限获取,以下是权限错误的类型
- CameraAccessDenied:当用户拒绝相机访问权限时抛出。
 - CameraAccessDeniedWithoutPrompt:仅限iOS。当用户先前拒绝该权限时抛出。iOS不允许再次提示警报对话框。用户必须进入“设置”>“隐私”>“相机”才能访问相机。
 - CameraAccessRestricted:仅限iOS。当摄像头访问受到限制且用户无法授予权限(家长控制)时抛出。
 - AudioAccessDenied:当用户拒绝音频访问权限时抛出。
 - AudioAccessDeniedWithoutPrompt:目前仅限iOS。当用户先前拒绝该权限时抛出。iOS不允许再次提示警报对话框。用户必须转到“设置”>“隐私”>“麦克风”才能启用音频访问。
 - AudioAccessRestricted:目前仅限iOS。当音频访问受到限制并且用户无法授予权限(家长控制)时抛出。
 
2.1 实现相机
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';late List<CameraDescription> _cameras;Future<void> main() async {WidgetsFlutterBinding.ensureInitialized();_cameras = await availableCameras();runApp(const CameraApp());
}/// CameraApp is the Main Application.
class CameraApp extends StatefulWidget {/// Default Constructorconst CameraApp({super.key});State<CameraApp> createState() => _CameraAppState();
}class _CameraAppState extends State<CameraApp> {late CameraController controller;void initState() {super.initState();controller = CameraController(_cameras[0], ResolutionPreset.max);controller.initialize().then((_) {if (!mounted) {return;}setState(() {});}).catchError((Object e) {if (e is CameraException) {switch (e.code) {case 'CameraAccessDenied':// Handle access errors here.break;default:// Handle other errors here.break;}}});}void dispose() {controller.dispose();super.dispose();}Widget build(BuildContext context) {if (!controller.value.isInitialized) {return Container();}return MaterialApp(home: CameraPreview(controller),);}
}
 
2.2 生命周期更改时处理相机
通过重写didChangeAppLifecycleState方法来处理生命周期更改,如下所示:
使用WidgetsBindingObserver
void didChangeAppLifecycleState(AppLifecycleState state) {final CameraController? cameraController = controller;// App state changed before we got the chance to initialize.if (cameraController == null || !cameraController.value.isInitialized) {return;}if (state == AppLifecycleState.inactive) {cameraController.dispose();} else if (state == AppLifecycleState.resumed) {_initializeCameraController(cameraController.description);}}
 
2.3 CameraPreview预览时图像变形问题更改
这个需要使用到具体Container的宽高和aspectRatio做处理
    if (controller != null && controller!.value.isInitialized) {// 设备像素比double deviceRatio = 1.0;if (widget.width! > widget.height!) {deviceRatio = widget.width! / widget.height!;} else {deviceRatio = widget.height! / widget.width!;}// 相机纵横比final double aspectRatio = controller!.value.aspectRatio;double scale = aspectRatio / deviceRatio;return Container(key: _cameraContainerGlobalKey,width: widget.width,height: widget.height,clipBehavior: Clip.hardEdge,decoration: BoxDecoration(color: Colors.transparent,borderRadius: BorderRadius.circular(20.r),),child: Stack(alignment: Alignment.center,clipBehavior: Clip.hardEdge,children: [Container(width: widget.width,height: widget.height,clipBehavior: Clip.hardEdge,decoration: BoxDecoration(color: Colors.transparent,),child: RepaintBoundary(key: _cameraViewGlobalKey,child: Transform.scale(scale: scale * aspectRatio,child: AspectRatio(aspectRatio: aspectRatio,child: Center(child: CameraPreview(controller!,),),),),),),),);
}
 
2.4 实现拍照功能
使用拍照功能,需要用到CameraController
Future<XFile?> takePicture() async {final CameraController? cameraController = controller;if (cameraController == null || !cameraController.value.isInitialized) {print('Error: select a camera first.');return null;}if (cameraController.value.isTakingPicture) {// A capture is already pending, do nothing.return null;}try {final XFile file = await cameraController.takePicture();print("takePicture file:${file.toString()}");return file;} on CameraException catch (e) {print("takePicture exception:${e.toString()}");return null;}}
 
获取到File,可以得到图片的path。
2.5 暂停及恢复预览
暂停及恢复预览
if (!cameraController.value.isPreviewPaused) {await cameraController.pausePreview();}
 
if (cameraController.value.isPreviewPaused) {await cameraController.resumePreview();}
 
2.6 获得图片后裁剪
裁剪图片这里使用的是插件:image
引入插件
image: ^4.0.17
实现裁剪
if (file != null) {// 保存到相册// await SaveToAlbumUtil.saveLocalImage(file.path);RenderBox renderBox = _cameraContainerGlobalKey.currentContext!.findRenderObject() as RenderBox;// offset.dx , offset.dy 就是控件的左上角坐标Offset offset = renderBox.localToGlobal(Offset.zero);//获取sizeSize size = renderBox.size;// 创建文件pathString imageDir = await PathUtil.createDirectory("local_images");String imagePath = '$imageDir/${TimeUtil.currentTimeMillis()}.png';// 获取当前设备的像素比double dpr = ui.window.devicePixelRatio;print("devicePixelRatio:${dpr}");print("offset:(${offset.dx},${offset.dy})--size:(${size.width},${size.height})");File? targetFile = await ImageUtil.cropImage(file.path, imagePath,x: (dpr * offset.dx).floor(),y: (dpr * offset.dy).floor(),width: (dpr * size.width).ceil(),height: (dpr * size.height).ceil());if (targetFile != null) {await SaveToAlbumUtil.saveLocalImage(targetFile.path);}
}
 
裁剪结果如图所示

 
三、小结
flutter开发实战-自定义相机camera功能,拍照及图片裁剪功能.
学习记录,每天不停进步。
相关文章:
flutter开发实战-自定义相机camera功能
flutter开发实战-自定义相机camera功能。 Flutter 本质上只是一个 UI 框架,运行在宿主平台之上,Flutter 本身是无法提供一些系统能力,比如使用蓝牙、相机、GPS等,因此要在 Flutter 中调用这些能力就必须和原生平台进行通信。 实现…...
重排链表——力扣143
文章目录 题目描述法一:寻找链表中点、链表逆序、链表合并 题目描述 法一:寻找链表中点、链表逆序、链表合并 void reorderList(ListNode* head){if(headnullptr){return;}// 找到中点 ListNode* mid FindMiddle(head);ListNode *h1head, *h2mid->ne…...
Lambda表达式常见的Local variable must be final or effectively final原因及解决办法
目录 Local variable must be final or effectively final错误原因 解决办法按照要求定义为final(不符合实情,很多时候是查库获取的变量值)使用原子类存储变量,保证一致性AtomicReference常用原子类 其它 Local variable must be …...
YOLOv5改进系列(16)——添加EMA注意力机制(ICASSP2023|实测涨点)
【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制 YOLOv5改进系列(2)——添加...
[SSM]GoF之代理模式
目录 十四、GoF之代理模式 14.1对代理模式的理解 14.2静态代理 14.3动态代理 14.3.1JDK动态代理 14.3.2CGLIB动态代理 十四、GoF之代理模式 14.1对代理模式的理解 场景:拍电影的时候,替身演员去代理演员完成表演。这就是一个代理模式。 演员为什…...
桥梁安全生命周期监测解决方案
一、方案背景 建筑安全是人们生产、经营、居住等经济生活和人身安全的基本保证,目前我国越来越多的建筑物逐 步接近或者已经达到了使用年限,使得建筑物不断出现各种安全隐患,对居民的人身安全和财产安全产 生不利影响,因此房…...
图技术在 LLM 下的应用:知识图谱驱动的大语言模型 Llama Index
LLM 如火如荼地发展了大半年,各类大模型和相关框架也逐步成型,可被大家应用到业务实际中。在这个过程中,我们可能会遇到一类问题是:现有的哪些数据,如何更好地与 LLM 对接上。像是大家都在用的知识图谱,现在…...
SpringBoot自动配置、启动器原理爆肝解析(干货满满)
文章目录 前言一、SpringBoot优势概要二、SpringBoot自动配置1. ☠注意☠2.自动配置详解 三、Starter(场景启动器)原理总结 前言 本文详细解析面试重点—SpringBoot自动配置原理、场景启动器原理,深入源码,直接上干货、绝不拖泥带…...
chrome扩展控制popup页面动态切换
文章目录 1、通过控制元素的显示隐藏达到popup页面切换的效果2、通过监听页面重新加载完成不同popup的切换3、直接修改popup页面location.href,无需刷新页面 1、通过控制元素的显示隐藏达到popup页面切换的效果 下面在mv2版本的API下完成 实际上通过控制页面元素实…...
【AI】《动手学-深度学习-PyTorch版》笔记(三):PyTorch常用函数
AI学习目录汇总 1、torch.arange 返回一维张量(一维数组),官网说明,常见的三种用法如下 输入:torch.arange(5) 输出:tensor([0, 1, 2, 3, 4]) 输入:torch.arange(5, 16) 输出:tensor([ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]) 输入:torch.arange(1, 25, 2) …...
某文化馆三维建模模型-glb格式-三维漫游-室内导航测试
资源描述 某文化馆某个楼层的三维建模模型,glb格式,适用于three.js开发,可用来做一些三维室内漫游测试和室内导航测试 资源下载地址...
网络安全 Day19-计算机网络基础知识04(网络协议)
计算机网络基础知识04(网络协议) 1. ARP1.1 ARP通讯原理1.2 arp欺骗1.3 ARP欺骗与预防1.4 排查ARP病毒 2. DHCP工作原理(自动分配内网IP)3. TCP协议三次握手、四次挥手原理4. DNS协议工作原理 1. ARP Linux查看arp:ar…...
Verilog语法学习——LV5_位拆分与运算
LV5_位拆分与运算 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 题目描述: 现在输入了一个压缩的16位数据,其实际上包含了四个数据…...
❤️创意网页:创意动态画布~缤纷移动涂鸦~图片彩色打码
✨博主:命运之光 🌸专栏:Python星辰秘典 🐳专栏:web开发(简单好用又好看) ❤️专栏:Java经典程序设计 ☀️博主的其他文章:点击进入博主的主页 前言:欢迎踏入…...
数值分析第六章节 用Python实现解线性方程组的迭代法
参考书籍:数值分析 第五版 李庆杨 王能超 易大义编 第5章 解线性方程组的迭代法 文章声明:如有发现错误,欢迎批评指正 文章目录 迭代法的基本概念雅可比迭代法与高斯-塞格尔迭代法雅可比迭代法高斯-塞格尔迭代法 迭代法的基本概念 6.1.1引言…...
【低代码专题方案】使用iPaaS平台下发数据,快捷集成MDM类型系统
01 场景背景 伴随着企业信息化建设日趋完善化、体系化,使用的应用系统越来越多,业务发展中沉淀了大量数据。主数据作为数据治理中枢,保存大量标准数据库,如何把庞大的数据下发到各个业务系统成了很棘手的问题。 传统的数据下发方…...
驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)
模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile 封装模块化驱动,可自由安装卸载驱动,便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…...
数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法
一、最短路径应用案例 例如从北京到上海旅游,有多条路可以到目的地,哪条路线最短,哪条路线最省钱,就是典型的最短路径问题。 二、最短路径问题分类 最短路径问题可以分为两类,第一类为:两点间最短路径。第…...
Windows Server 2012 能使用的playwright版本
由于在harkua_bot里面使用到了playwright,我的服务器又是Windows Server 2012 R2,最新版playwright不支持Windows Server 2012 R2,支持Windows Server 2016以上,所以有了这个需求 https://cdn.npmmirror.com/binaries/playwright…...
css实现溢出变为省略号
单行文本溢出省略 text-overflow:规定当文本溢出时,显示省略符号来代表被修剪的文本 white-space:设置文字在一行显示,不能换行 overflow:文字长度超出限定宽度,则隐藏超出的内容overflow设为hidden&#…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
React Native 导航系统实战(React Navigation)
导航系统实战(React Navigation) React Navigation 是 React Native 应用中最常用的导航库之一,它提供了多种导航模式,如堆栈导航(Stack Navigator)、标签导航(Tab Navigator)和抽屉…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
学校招生小程序源码介绍
基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码,专为学校招生场景量身打造,功能实用且操作便捷。 从技术架构来看,ThinkPHP提供稳定可靠的后台服务,FastAdmin加速开发流程,UniApp则保障小程序在多端有良好的兼…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
IT供电系统绝缘监测及故障定位解决方案
随着新能源的快速发展,光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域,IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选,但在长期运行中,例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
