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

news2025/5/15 21:57:29

接上文 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:PipStateFailed
                                 error:@"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:_contentView
                                          atIndex: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
    [_contentViewOriginalParentView
        removeConstraints:_contentViewOriginalParentView.constraints.copy];
    [_contentViewOriginalParentView
        addConstraints:_contentViewOriginalParentViewConstraints];
  }
}

支持动态设置PipWindow窗口大小

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

if (options.preferredContentSize.width > 0 &&
    options.preferredContentSize.height > 0) {
  [_pipView
      updateFrameSize: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.coloradmin.cn/o/2375635.html

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

相关文章

数据库管理-第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编码&…

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…

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…

uniapp小程序轮播图高度自适应优化详解

在微信小程序开发过程中,轮播图组件(swiper)是常用的UI元素,但在实际应用中经常遇到高度不匹配导致的空白问题。本文详细记录了一次轮播图高度优化的完整过程,特别是针对固定宽高比图片的精确适配方案。 问题背景 在开发"零工市场&quo…

基于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&#xff0…

PPT图表怎么制作?说5款自己使用过的PPT图表制作工具

PPT图表怎么制作?准备一份吸引人的PPT演示文稿时,图表往往能起到画龙点睛的作用。但是,对于很多人来说,制作既美观又专业的图表却不是一件容易的事情。今天,我们就来聊聊如何利用一些优秀的工具制作PPT图表。 1、亿图图…

[传输层]TCP协议

文章目录 报文格式连接管理可靠传输 面向连接的传输层协议 每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的 TCP提供可靠有序,不丢不重 TCP是面向字节流的 TCP工作模型: 发送方有一个缓存,缓存: 1.待发送 2…

Linux(1)编译链接和gcc

1、gcc分布编译链接 (1)预编译 gcc -E main.c -o main.i (2)编译 gcc -S main.i -o main.s (3)汇编 gcc -c main.s -o main.o (4)链接 gcc main.o -o main 执行&#xff1a…

【Java ee初阶】网络编程 UDP socket

网络编程 socket api 是传输层提供的api。 UDP 无连接,不可靠传输,面向数据报,全双工。 TCP 有链接,可靠传输,面向字节流,全双工。 UDP socket api 数据报 DatagrammSocket 代表了操作系统中的socket文…