当前位置: 首页 > news >正文

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 框架&#xff0c;运行在宿主平台之上&#xff0c;Flutter 本身是无法提供一些系统能力&#xff0c;比如使用蓝牙、相机、GPS等&#xff0c;因此要在 Flutter 中调用这些能力就必须和原生平台进行通信。 实现…...

重排链表——力扣143

文章目录 题目描述法一&#xff1a;寻找链表中点、链表逆序、链表合并 题目描述 法一&#xff1a;寻找链表中点、链表逆序、链表合并 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&#xff08;不符合实情&#xff0c;很多时候是查库获取的变量值&#xff09;使用原子类存储变量&#xff0c;保证一致性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对代理模式的理解 场景&#xff1a;拍电影的时候&#xff0c;替身演员去代理演员完成表演。这就是一个代理模式。 演员为什…...

桥梁安全生命周期监测解决方案

一、方案背景 建筑安全是人们生产、经营、居住等经济生活和人身安全的基本保证&#xff0c;目前我国越来越多的建筑物逐 步接近或者已经达到了使用年限&#xff0c;使得建筑物不断出现各种安全隐患&#xff0c;对居民的人身安全和财产安全产 生不利影响&#xff0c;因此房…...

图技术在 LLM 下的应用:知识图谱驱动的大语言模型 Llama Index

LLM 如火如荼地发展了大半年&#xff0c;各类大模型和相关框架也逐步成型&#xff0c;可被大家应用到业务实际中。在这个过程中&#xff0c;我们可能会遇到一类问题是&#xff1a;现有的哪些数据&#xff0c;如何更好地与 LLM 对接上。像是大家都在用的知识图谱&#xff0c;现在…...

SpringBoot自动配置、启动器原理爆肝解析(干货满满)

文章目录 前言一、SpringBoot优势概要二、SpringBoot自动配置1. ☠注意☠2.自动配置详解 三、Starter&#xff08;场景启动器&#xff09;原理总结 前言 本文详细解析面试重点—SpringBoot自动配置原理、场景启动器原理&#xff0c;深入源码&#xff0c;直接上干货、绝不拖泥带…...

chrome扩展控制popup页面动态切换

文章目录 1、通过控制元素的显示隐藏达到popup页面切换的效果2、通过监听页面重新加载完成不同popup的切换3、直接修改popup页面location.href&#xff0c;无需刷新页面 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格式-三维漫游-室内导航测试

资源描述 某文化馆某个楼层的三维建模模型&#xff0c;glb格式&#xff0c;适用于three.js开发&#xff0c;可用来做一些三维室内漫游测试和室内导航测试 资源下载地址...

网络安全 Day19-计算机网络基础知识04(网络协议)

计算机网络基础知识04&#xff08;网络协议&#xff09; 1. ARP1.1 ARP通讯原理1.2 arp欺骗1.3 ARP欺骗与预防1.4 排查ARP病毒 2. DHCP工作原理&#xff08;自动分配内网IP&#xff09;3. TCP协议三次握手、四次挥手原理4. DNS协议工作原理 1. ARP Linux查看arp&#xff1a;ar…...

Verilog语法学习——LV5_位拆分与运算

LV5_位拆分与运算 题目来源于牛客网 [牛客网在线编程_Verilog篇_Verilog快速入门 (nowcoder.com)](https://www.nowcoder.com/exam/oj?page1&tabVerilog篇&topicId301) 题目 题目描述&#xff1a; 现在输入了一个压缩的16位数据&#xff0c;其实际上包含了四个数据…...

❤️创意网页:创意动态画布~缤纷移动涂鸦~图片彩色打码

✨博主&#xff1a;命运之光 &#x1f338;专栏&#xff1a;Python星辰秘典 &#x1f433;专栏&#xff1a;web开发&#xff08;简单好用又好看&#xff09; ❤️专栏&#xff1a;Java经典程序设计 ☀️博主的其他文章&#xff1a;点击进入博主的主页 前言&#xff1a;欢迎踏入…...

数值分析第六章节 用Python实现解线性方程组的迭代法

参考书籍&#xff1a;数值分析 第五版 李庆杨 王能超 易大义编 第5章 解线性方程组的迭代法 文章声明&#xff1a;如有发现错误&#xff0c;欢迎批评指正 文章目录 迭代法的基本概念雅可比迭代法与高斯-塞格尔迭代法雅可比迭代法高斯-塞格尔迭代法 迭代法的基本概念 6.1.1引言…...

【低代码专题方案】使用iPaaS平台下发数据,快捷集成MDM类型系统

01 场景背景 伴随着企业信息化建设日趋完善化、体系化&#xff0c;使用的应用系统越来越多&#xff0c;业务发展中沉淀了大量数据。主数据作为数据治理中枢&#xff0c;保存大量标准数据库&#xff0c;如何把庞大的数据下发到各个业务系统成了很棘手的问题。 传统的数据下发方…...

驱动开发 day3 (模块化驱动启动led,蜂鸣器,风扇,震动马达)

模块化驱动启动led,蜂鸣器,风扇,震动马达并加上Makefile 封装模块化驱动&#xff0c;可自由安装卸载驱动&#xff0c;便于驱动更新(附图) 1.安装模块驱动同时初始化各个设备并使能 2.该驱动会自动创建驱动节点. 3.通过c函数程序输入控制各个设备 4.卸载模块驱动 //编译驱动…...

数据结构与算法基础-学习-27-图之最短路径之Dijkstra(迪杰斯特拉)算法

一、最短路径应用案例 例如从北京到上海旅游&#xff0c;有多条路可以到目的地&#xff0c;哪条路线最短&#xff0c;哪条路线最省钱&#xff0c;就是典型的最短路径问题。 二、最短路径问题分类 最短路径问题可以分为两类&#xff0c;第一类为&#xff1a;两点间最短路径。第…...

Windows Server 2012 能使用的playwright版本

由于在harkua_bot里面使用到了playwright&#xff0c;我的服务器又是Windows Server 2012 R2&#xff0c;最新版playwright不支持Windows Server 2012 R2&#xff0c;支持Windows Server 2016以上&#xff0c;所以有了这个需求 https://cdn.npmmirror.com/binaries/playwright…...

css实现溢出变为省略号

单行文本溢出省略 text-overflow&#xff1a;规定当文本溢出时&#xff0c;显示省略符号来代表被修剪的文本 white-space&#xff1a;设置文字在一行显示&#xff0c;不能换行 overflow&#xff1a;文字长度超出限定宽度&#xff0c;则隐藏超出的内容overflow设为hidden&#…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

循环冗余码校验CRC码 算法步骤+详细实例计算

通信过程&#xff1a;&#xff08;白话解释&#xff09; 我们将原始待发送的消息称为 M M M&#xff0c;依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)&#xff08;意思就是 G &#xff08; x ) G&#xff08;x) G&#xff08;x) 是已知的&#xff09;&#xff0…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

令牌桶 滑动窗口->限流 分布式信号量->限并发的原理 lua脚本分析介绍

文章目录 前言限流限制并发的实际理解限流令牌桶代码实现结果分析令牌桶lua的模拟实现原理总结&#xff1a; 滑动窗口代码实现结果分析lua脚本原理解析 限并发分布式信号量代码实现结果分析lua脚本实现原理 双注解去实现限流 并发结果分析&#xff1a; 实际业务去理解体会统一注…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

基于江科大stm32屏幕驱动,实现OLED多级菜单(动画效果),结构体链表实现(独创源码)

引言 在嵌入式系统中&#xff0c;用户界面的设计往往直接影响到用户体验。本文将以STM32微控制器和OLED显示屏为例&#xff0c;介绍如何实现一个多级菜单系统。该系统支持用户通过按键导航菜单&#xff0c;执行相应操作&#xff0c;并提供平滑的滚动动画效果。 本文设计了一个…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...

npm install 相关命令

npm install 相关命令 基本安装命令 # 安装 package.json 中列出的所有依赖 npm install npm i # 简写形式# 安装特定包 npm install <package-name># 安装特定版本 npm install <package-name><version>依赖类型选项 # 安装为生产依赖&#xff08;默认&…...

【向量库】Weaviate 搜索与索引技术:从基础概念到性能优化

文章目录 零、概述一、搜索技术分类1. 向量搜索&#xff1a;捕捉语义的智能检索2. 关键字搜索&#xff1a;精确匹配的传统方案3. 混合搜索&#xff1a;语义与精确的双重保障 二、向量检索技术分类1. HNSW索引&#xff1a;大规模数据的高效引擎2. Flat索引&#xff1a;小规模数据…...