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,你的加星和点赞,将是我继续改进最大的动力
相关文章:

Flutter PIP 插件 ---- 为iOS 重构PipController, Demo界面,更好的体验
接上文 Flutter PIP 插件 ---- 新增PipActivity,Android 11以下支持自动进入PIP Mode 项目地址 PIP, pub.dev也已经同步发布 pip 0.0.3,你的加星和点赞,将是我继续改进最大的动力 在之前的界面设计中,还原动画等体验一…...
Redis 基本命令与操作全面解析:从入门到实战
前言 Redis 作为高性能内存数据库,其丰富的命令体系是发挥强大功能的基础。掌握 Redis 的基本命令,不仅能实现数据的高效读写,还能深入理解其内存模型与工作机制。本文将系统梳理 Redis 的核心命令,涵盖连接操作、键管理、数据类…...

数据库管理-第325期 ADG Failover后该做啥(20250513)
数据库管理325期 2025-05-13 数据库管理-第325期 ADG Failover后该做啥(20250513)1 故障处置2 恢复原主库3 其他操作总结 数据库管理-第325期 ADG Failover后该做啥(20250513) 作者:胖头鱼的鱼缸(尹海文&a…...

SQLi-Labs 第21-24关
Less-21 http://127.0.0.1/sqli-labs/Less-21/ 1,抓个请求包看看 分析分析cookie被base64URL编码了,解码之后就是admin 2,那么这个网站的漏洞利用方式也是和Less-20关一样的,只是攻击语句要先base64编码,再URL编码&…...
Oracle — 数据管理
介绍 Oracle数据库作为全球领先的关系型数据库管理系统,其数据管理能力以高效性、安全性和智能化为核心。系统通过多维度技术实现海量数据的存储与实时处理,支持高并发事务操作与复杂分析查询,满足企业关键业务需求。在安全领域,O…...
在 Qt Creator 中为 QDockWidget 设置隐藏和显示按钮
在 Qt Creator 中为 QDockWidget 设置隐藏和显示按钮 是的,QDockWidget 内置了隐藏和显示的功能,可以通过以下几种方式实现: 1. 使用 QDockWidget 自带的关闭按钮 QDockWidget 默认带有一个关闭按钮,可以通过以下代码启用&…...
LS-NET-012-TCP的交互过程详解
LS-NET-012-TCP的交互过程详解 附加:TCP如何保障数据传输 TCP的交互过程详解 一、TCP协议核心交互流程 TCP协议通过三次握手建立连接、数据传输、四次挥手终止连接三大阶段实现可靠传输。整个过程通过序列号、确认应答、窗口控制等机制保障传输可靠性。 1.1 三次…...
每日算法刷题Day1 5.9:leetcode数组3道题,用时1h
1.LC寻找数组的中心索引(简单) 数组和字符串 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台 思想: 计算总和和左侧和,要让左侧和等于右侧和,即左侧和总和-左侧和-当前数字 代码 c代码: class Solution { public:i…...
解构认知边界:论万能方法的本体论批判与方法论重构——基于跨学科视阈的哲学-科学辩证
一、哲学维度的本体论批判 (1)理性主义的坍缩:从笛卡尔幻想到哥德尔陷阱 笛卡尔在《方法论》中构建的理性主义范式,企图通过"普遍怀疑-数学演绎"双重机制确立绝对方法体系。然而哥德尔不完备定理(Gdel, 19…...

PVE WIN10直通无线网卡蓝牙
在 Proxmox VE (PVE) 中直通 Intel AC3165 无线网卡的 **蓝牙模块**(通常属于 USB 设备,而非 PCIe 设备)需要特殊处理,因为它的蓝牙部分通常通过 USB 连接,而 Wi-Fi 部分才是 PCIe 设备。以下是详细步骤: …...

第六节第二部分:抽象类的应用-模板方法设计模式
模板方法设计模式的写法 建议使用final关键字修饰模板方法 总结 代码: People(父类抽象类) package com.Abstract3; public abstract class People {/*设计模板方法设计模式* 1.定义一个模板方法出来*/public final void write(){System.out.println("\t\t\t…...

在另一个省发布抖音作品,IP属地会随之变化吗?
你是否曾有过这样的疑惑:出差旅游时在外地发布了一条抖音视频,评论区突然冒出“IP怎么显示xx省了?”的提问?随着各大社交平台上线“IP属地”功能,用户的地理位置标识成为公开信息,而属地显示的“灵敏性”也…...

卷积神经网络-从零开始构建一个卷积神经网络
目录 一、什么是卷积神经网络CNN 1.1、核心概念 1.2、卷积层 二、什么是卷积计算 2.1、卷积计算的例子: 2.2、点积 2.3、卷积与点积的关系 2.4、Padding(填充) 2.4.1、Padding的主要作用 1、控制输出特征图尺寸 2、保留边缘信息 3. 支持深层网络训练 2.4.2、Str…...
力扣-101.对称二叉树
题目描述 给你一个二叉树的根节点 root , 检查它是否轴对称。 class Solution { public:bool check(TreeNode* p,TreeNode* q){if(!p&&!q)return true;if(!p&&q||!q&&p)return false;if(p->val!q->val)return false;return check(p…...
Tomcat和Nginx的主要区别
1、功能定位 Nginx:核心是高并发HTTP服务器和反向代理服务器,擅长处理静态资源(如HTML、图片)和负载均衡。Tomcat:是Java应用服务器,主要用于运行动态内容(如JSP、Servlet)…...
贪心算法:最小生成树
假设无向图为: A-B:1 A-C:3 B-C:1 B-D:4 C-D:1 C-E:5 D-E:6 一、使用Prim算法: public class Prim {//声明了两个静态常量,用于辅助 Prim 算法的实现private static final int V 5;//点数private static final int INF Integer.MA…...

uniapp-文件查找失败:‘@dcloudio/uni-ui/lib/uni-icons/uni-icons.vue‘
uniapp-文件查找失败:‘dcloudio/uni-ui/lib/uni-icons/uni-icons.vue’ 今天在HBuilderX中使用uniapp开发微信小程序时遇到了这个问题,就是找不到uni-ui组件 当时创建项目,选择了一个中间带的底部带选项卡模板,并没有选择内置u…...

Vue2.x 和 Vue3.x 对比-差异
Vue3的优点 diff算法的提升 vue2中的虚拟DOM是全量的对比,也就是不管是写死的还是动态节点都会一层层比较,浪费时间在静态节点上。 vue3新增静态标记(patchflag ),与之前虚拟节点对比,只对比带有patch fla…...

MacOS 用brew 安装、配置、启动Redis
MacOS 用brew 安装、配置、启动Redis 一、安装 brew install redis 二、启动 brew services start redis 三、用命令行检测 set name tom get name...

agentmain对业务的影响
前面一篇已经说了java agent技术主要有premain和agentmain两种形式,如果大部分业务已经在线上运行的话,不方便用premain的方式来实现,所以agentmain的方式是更加通用、灵活的 由于RASP是与用户业务运行在同一个jvm中的 ,所以RASP…...
精益数据分析(56/126):创业阶段的划分与精益数据分析实践
精益数据分析(56/126):创业阶段的划分与精益数据分析实践 在创业和数据分析的探索之旅中,理解创业阶段的划分以及与之对应的精益数据分析方法至关重要。今天,依旧怀揣着与大家共同进步的心态,深入研读《精…...
archlinux中挂载macOS的硬盘
问: 你好,我如何在archlinux中挂载macOS的硬盘呢?/dev/sda4 5344161792 7813773311 2469611520 1.2T Apple HFS/HFS AI回答: 你好!在 Arch Linux 中挂载 macOS 的 HFS 或 HFS 硬盘(例如 /dev/sda4&#x…...
JVM Optimization Learning(七)-GC
一、JVM Optimization 1、进程溢出调查 模拟 如何开启GC日志 如何开启GC日志 一般来说,JDK8及以下版本通过以下参数来开启GC日志: -XX:PrintGCDetails -XX:PrintGCDateStamps -Xloggc:gc.log如果是在JDK9及以上的版本,则格式略有不同&…...

uniapp小程序轮播图高度自适应优化详解
在微信小程序开发过程中,轮播图组件(swiper)是常用的UI元素,但在实际应用中经常遇到高度不匹配导致的空白问题。本文详细记录了一次轮播图高度优化的完整过程,特别是针对固定宽高比图片的精确适配方案。 问题背景 在开发"零工市场&quo…...
CSS从入门到精通:全面解析CSS核心知识体系
引言 CSS(层叠样式表)是前端开发的基石,掌握其核心知识能显著提升页面设计与布局能力。本文基于系统化学习资料,深入讲解CSS语法、选择器优先级、盒子模型、定位等核心概念,结合代码示例与实用技巧,助你从入…...

基于ESP32控制的机器人摄像头车
DIY Wi-Fi 控制的机器人摄像头车:从零开始的智能探索之旅 在当今科技飞速发展的时代,机器人技术已经逐渐走进了我们的生活。今天,我将带你一起探索如何制作一个 Wi-Fi 控制的机器人摄像头车,它不仅可以远程操控,还能通…...

基于STM32的LCD信号波形和FFT频谱显示
一、项目准备 主要利用LCD驱动中的画点和画连线函数,驱动是正点原子给我写好了的画点和画线的函数等些相关函数 void LCD_Draw_Circle(u16 x0,u16 y0,u8 r); //画圆 void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //画线 二、画波形图函数实…...

(9)被宏 QT_DEPRECATED_VERSION_X_6_0(“提示内容“) 修饰的函数,在 Qt6 中使用时,会被编译器提示该函数已过时
(1)起因是看到 Qt 的官方源代码里有这样的写法: #if QT_DEPRECATED_SINCE(6, 0) //里面的都是废弃的成员函数QT_WARNING_PUSHQT_WARNING_DISABLE_DEPRECATEDQT_DEPRECATED_VERSION_X_6_0("Use the constructor taking a QMetaType inst…...

关于mac配置hdc(鸿蒙)
关于mac配置hdc(鸿蒙) 在最开始配置的hdc -v时候老是出现格式不匹配 于是乎在网上找官网也不行,最后在csdn上找到了这篇文章Mac配置hdc才有的头绪 环境变量的问题 自己做一个简单的总结 首先在访达里面打开ide 打开之后输入下面的命令,一步一步的找…...

是 OpenCV 的 CUDA 模块中用于在 GPU 上对图像或矩阵进行转置操作函数cv::cuda::transpose
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 cv::cuda::transpose 是 OpenCV 的 CUDA 模块中的一个函数,用于在 GPU 上对图像或矩阵进行转置操作(Transpose࿰…...