Flutter PIP 插件 ---- 为iOS 重构PipController, Demo界面,更好的体验

接上文 Flutter PIP 插件 ---- 新增PipActivity,Android 11以下支持自动进入PIP Mode

项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

在之前的界面设计中,还原动画等体验一直不太好,遂优化一下,现在体验效果看起来更好了,
唯一一个还没搞定的是应用内还原的动画,应用内还原的时候,有一个从小到达逐渐拉伸的效果,猜测可能是和图片的渲染有关?有大佬能指点一二不?
请添加图片描述

不再获取PipViewController

前面也讲到这个比较危险,虽然多方求证似乎也没什么,但还是怕,所以改成查找PipWindow,并在pictureInPictureControllerDidStartPictureInPicture通知中把自渲染View添加到rootView中去

- (void)pictureInPictureControllerDidStartPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {PIP_LOG(@"pictureInPictureControllerDidStartPictureInPicture");#if USE_PIP_VIEW_CONTROLLER// if you use the pipViewController, you must call this every time to bring// the content view to the front, otherwise the content view will not be// visible and covered by the pip host view.if (_pipViewController) {[_pipViewController.view bringSubviewToFront:_contentView];}
#else// TODO @sylar: check if this is the best way to do this, what will happen if// we have multiple windows? what if the root view controller is not a// UIViewController?UIWindow *window = [[UIApplication sharedApplication] windows].firstObject;if (window) {UIViewController *rootViewController = window.rootViewController;UIView *superview = rootViewController.view.superview;[self insertContentViewIfNeeded:superview];} else {PIP_LOG(@"pictureInPictureControllerDidStartPictureInPicture: window is nil");[_pipStateDelegate pipStateChanged:PipStateFailederror:@"Can not find the pip window"];return;}
#endif_isPipActived = YES;[_pipStateDelegate pipStateChanged:PipStateStarted error:nil];
}

遗留项是,这个查找PipWindow的方法靠不靠谱?有其他方法但是看起来也不靠谱

不再每次都将自渲染UIView从PipWindow移除

观察到一个现象是,如果是依赖PipViewController在 pictureInPictureControllerWillStartPictureInPicture 中添加UIView,还必须得在 pictureInPictureControllerDidStartPictureInPicture 中调用一次 bringSubviewToFront,否则的话你会比系统自动添加的View早添加,导致你的层级在下面;改用通过获取PipWindow方式后,就不用在bringSubviewToFront,因为不是一个parent了。
在这里插入图片描述
另外一些场景下可能会创建一个悬空的UIView用来做渲染,这样的话我们就没必要每次都把他从PipWindow上移除还原到父parent上,可以在PipWindow显示的一瞬间就立即看到渲染的内容

- (void)pictureInPictureControllerDidStopPictureInPicture:(AVPictureInPictureController *)pictureInPictureController {PIP_LOG(@"pictureInPictureControllerDidStopPictureInPicture");// restore the content view in// pictureInPictureControllerDidStopPictureInPicture will have the best user// experience.[self restoreContentViewIfNeeded];_isPipActived = NO;[_pipStateDelegate pipStateChanged:PipStateStopped error:nil];
}- (void)restoreContentViewIfNeeded {if (_contentView == nil) {PIP_LOG(@"restoreContentViewIfNeeded: contentView is nil");return;}// do not restore the content view if the original parent view is nil or// the content view is already in the original parent view.// keep the content view in the pip view controller will make the user// experience better, the pip content view will be visible immediately.if (_contentViewOriginalParentView == nil ||[_contentViewOriginalParentView.subviews containsObject:_contentView]) {PIP_LOG(@"restoreContentViewIfNeeded: _contentViewOriginalParentView is nil or "@"contentView is already in the original parent view");return;}[_contentView removeFromSuperview];PIP_LOG(@"restoreContentViewIfNeeded: contentView is removed from the original "@"parent view");if (_contentViewOriginalParentView != nil) {// in case that the subviews of _contentViewOriginalParentView has been// changed, we need to get the real index of the content view.NSUInteger trueIndex = MIN(_contentViewOriginalParentView.subviews.count,_contentViewOriginalIndex);[_contentViewOriginalParentView insertSubview:_contentViewatIndex:trueIndex];PIP_LOG(@"restoreContentViewIfNeeded: contentView is added to the original "@"parent view "@"at index: %lu",trueIndex);// restore the original frame_contentView.frame = _contentViewOriginalFrame;// restore the original constraints[_contentView removeConstraints:_contentView.constraints.copy];[_contentView addConstraints:_contentViewOriginalConstraints];// restore the original translatesAutoresizingMaskIntoConstraints_contentView.translatesAutoresizingMaskIntoConstraints =_contentViewOriginalTranslatesAutoresizingMaskIntoConstraints;// restore the original parent view[_contentViewOriginalParentViewremoveConstraints:_contentViewOriginalParentView.constraints.copy];[_contentViewOriginalParentViewaddConstraints:_contentViewOriginalParentViewConstraints];}
}

支持动态设置PipWindow窗口大小

这个没什么好说的,修改创建contentSource的时候的sampleBufferDisplayer的大小就可以动态修改PipWindow窗口大小,判断各种对象都已经有了的话就只修改大小而不用重新创建controller就行了

if (options.preferredContentSize.width > 0 &&options.preferredContentSize.height > 0) {[_pipViewupdateFrameSize:CGSizeMake(options.preferredContentSize.width,options.preferredContentSize.height)];
}

重要的事情说三遍

项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905404.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Ansible】之inventory主机清单

前言 本篇博客主要解释Ansible主机清单的相关配置知识 一、inventory 主机清单 Inventory支持对主机进行分组,每个组内可以定义多个主机,每个主机都可以定义在任何一个或多个主机组内。 如果是名称类似的主机,可以使用列表的方式表示各个主机…

基于几何布朗运动的股价预测模型构建与分析

基于几何布朗运动的股价预测模型构建与分析 摘要 本文建立基于几何布朗运动的股价预测模型,结合极大似然估计与蒙特卡洛模拟,推导股价条件概率密度函数并构建动态预测区间。实证分析显示模型在标普500指数预测中取得89%的覆盖概率,波动率估…

【前端】【JavaScript】【总复习】四万字详解JavaScript知识体系

JavaScript 前端知识体系 📌 说明:本大纲从基础到高级、从语法到应用、从面试到实战,分层级讲解 JavaScript 的核心内容。 一、JavaScript 基础语法 1.1 基本概念 1.1.1 JavaScript 的发展史与用途 1. 发展简史 1995 年:JavaS…

[Java实战]Spring Boot 3 整合 Apache Shiro(二十一)

[Java实战]Spring Boot 3 整合 Apache Shiro(二十一) 引言 在复杂的业务系统中,安全控制(认证、授权、加密)是核心需求。相比于 Spring Security 的重量级设计,Apache Shiro 凭借其简洁的 API 和灵活的扩…

PyTorch API 6 - 编译、fft、fx、函数转换、调试、符号追踪

文章目录 torch.compiler延伸阅读 torch.fft快速傅里叶变换辅助函数 torch.func什么是可组合的函数变换?为什么需要可组合的函数变换?延伸阅读 torch.futurestorch.fx概述编写转换函数图结构快速入门图操作直接操作计算图使用 replace_pattern() 进行子图…

可观测性方案怎么选?SelectDB vs Elasticsearch vs ClickHouse

可观测性(Observability)是指通过系统的外部输出数据,推断其内部状态的能力。可观测性平台通过采集、存储、可视化分析三大可观测性数据:日志(Logging)、链路追踪(Tracing)和指标&am…

机器人厨师上岗!AI在餐饮界掀起新风潮!

想要了解人工智能在其他各个领域的应用,可以查看下面一篇文章 《AI在各领域的应用》 餐饮业是与我们日常生活息息相关的行业,而人工智能(AI)正在迅速改变这个传统行业的面貌。从智能点餐到食材管理,再到个性化推荐&a…

Linux动态库静态库总结

静态库生成 g -c mylib.cpp -o mylib.o ar rcs libmylib.a mylib.o 动态库生成 g -fPIC -shared mylib.cpp -o libmylib.so -fPIC:生成位置无关代码(Position-Independent Code),对动态库必需。 库文件使用: 静态库&…

通过user-agent来源判断阻止爬虫访问网站,并防止生成[ error ] NULL日志

一、TP5.0通过行为&#xff08;Behavior&#xff09;拦截爬虫并避免生成 [ error ] NULL 错误日志 1. 创建行为类&#xff08;拦截爬虫&#xff09; 在 application/common/behavior 目录下新建BlockBot.php &#xff0c;用于识别并拦截爬虫请求&#xff1a; <?php name…

OpenHarmony平台驱动开发(十五),SDIO

OpenHarmony平台驱动开发&#xff08;十五&#xff09; SDIO 概述 功能简介 SDIO&#xff08;Secure Digital Input and Output&#xff09;由SD卡发展而来&#xff0c;与SD卡统称为MMC&#xff08;MultiMediaCard&#xff09;&#xff0c;二者使用相同的通信协议。SDIO接口…

使用FastAPI和React以及MongoDB构建全栈Web应用03 全栈开发快速入门

一、什么是全栈开发 A full-stack web application is a complete software application that encompasses both the frontend and backend components. It’s designed to interact with users through a web browser and perform actions that involve data processing and …

Coco AI 开源应用程序 - 搜索、连接、协作、您的个人 AI 搜索和助手,都在一个空间中。

一、软件介绍 文末提供程序和源码下载 Coco AI 是一个统一的搜索平台&#xff0c;可将您的所有企业应用程序和数据&#xff08;Google Workspace、Dropbox、Confluent Wiki、GitHub 等&#xff09;连接到一个功能强大的搜索界面中。此存储库包含为桌面和移动设备构建的 Coco 应…

CSS经典布局之圣杯布局和双飞翼布局

目标&#xff1a; 中间自适应&#xff0c;两边定宽&#xff0c;并且三栏布局在一行展示。 圣杯布局 实现方法&#xff1a; 通过float搭建布局margin使三列布局到一行上relative相对定位调整位置&#xff1b; 给外部容器添加padding&#xff0c;通过相对定位调整左右两列的…

# 实时英文 OCR 文字识别:从摄像头到 PyQt5 界面的实现

实时英文 OCR 文字识别&#xff1a;从摄像头到 PyQt5 界面的实现 引言 在数字化时代&#xff0c;文字识别技术&#xff08;OCR&#xff09;在众多领域中发挥着重要作用。无论是文档扫描、车牌识别还是实时视频流中的文字提取&#xff0c;OCR 技术都能提供高效且准确的解决方案…

<C#>log4net 的配置文件配置项详细介绍

log4net 是一个功能强大的日志记录工具&#xff0c;通过配置文件可以灵活地控制日志的输出方式、格式、级别等。以下是对 log4net 配置文件常见配置项的详细介绍&#xff1a; 根元素 <log4net> 这是 log4net 配置文件的根元素&#xff0c;所有配置项都要包含在该元素内…

编译docker版openresty

使用alpine为基础镜像 # 使用Alpine作为基础镜像 FROM alpine:3.18# 替换为阿里云镜像源&#xff0c;并安装必要的依赖 RUN sed -i s|https://dl-cdn.alpinelinux.org/alpine|https://mirrors.aliyun.com/alpine|g /etc/apk/repositories && \apk add --no-cache \bui…

conda 输出指定python环境的库 输出为 yaml文件

conda 输出指定python环境的库 输出为 yaml文件。 有时为了项目部署&#xff0c;需要匹配之前的python环境&#xff0c;需要输出对应的python依赖库。 假设你的目标环境名为 myenv&#xff0c;运行以下命令&#xff1a; conda env export -n myenv > myenv_environment.ym…

[Java][Leetcode middle] 121. 买卖股票的最佳时机

暴力循环 总是以最低的价格买入&#xff0c;以最高的价格卖出: 例如第一天买入&#xff0c;去找剩下n-1天的最高价格&#xff0c;计算利润 依次计算到n-1天买入&#xff1b; 比较上述利润 // 运行时间超时。 o(n^2)public int maxProfit1(int[] prices) {int profit 0;for (i…

克隆虚拟机组成集群

一、克隆虚拟机 1. 准备基础虚拟机 确保基础虚拟机已安装好操作系统&#xff08;如 Ubuntu&#xff09;、Java 和 Hadoop。关闭防火墙并禁用 SELinux&#xff08;如适用&#xff09;&#xff1a; bash sudo ufw disable # Ubuntu sudo systemctl disable firewalld # CentO…

记录一次使用thinkphp使用PhpSpreadsheet扩展导出数据,解决身份证号码等信息科学计数法问题处理

PhpSpreadsheet官网 PhpSpreadsheet安装 composer require phpoffice/phpspreadsheet使用composer安装时一定要下载php对应的版本&#xff0c;下载之前使用php -v检查当前php版本 简单使用 <?php require vendor/autoload.php;use PhpOffice\PhpSpreadsheet\Spreadshee…