ios播放器横竖屏切换的问题

所有的视频类App都会面临一个播放器横竖屏切换的问题,之前一直使用KVO强制修改设备方向达到竖屏转为横屏。

UIDevice.current.setValue(value, forKey: "orientation")

目前看来,优酷视频貌似依然使用的这个方法,具体表现为statusBar会跟着屏幕做旋转动画,而且播放器下的其他控件会转到横屏布局。

但是这个方法是非官方提供的API,随着系统版本的更迭有可能会失效。

所以许多公司采用了modal出一个只支持横屏的控制器来达到横竖屏切换的目的。

思路

有以下两种方法实现。

方法1

竖屏转横屏时:由竖屏控制器做一个播放器由小变大,并且旋转为横屏的动画,动画结束时做一个无动画的present

横屏转竖屏时:做一个无动画的dimiss,dimiss完成后,依然由竖屏控制器做播放器由大变小并且旋转回原处的动画。

目前看来,爱奇艺和bilibili貌似使用这个方式,具体表现为竖屏切横屏时,播放器动画完成后,statusBar无动画转为横屏;横屏切竖屏时,statusBar先无动画转为竖屏,然后才开始播放器动画。

这种方法的坑

问题

但是目前这个方法有一个问题,就是在横屏转竖屏时,画面偶尔会闪一下。

问题分析

画面偶尔会闪一下,是在默认的模式下,控制器的.modalPresentationStyle = UIModalPresentationStyle.fullScreen,此时,当控制器A present 出控制器B,完成present动作后,控制器B的view会添加进一个UITransitionView类型的View中(即我们在自定义转场动画时的transitionContext.containerView),UITransitionView是直接添加在Window上的,而控制器A的view会暂时从视图层级中移除。当无动画dimiss时,UITransitionView先从Window移除,然后控制器A的View在添加到window上,在这中间有可能会造成闪动。

所以只要保证完成present动作后,控制器A的view依然保持在视图层级中即可。

解决方案

解决方案1

在UIModalPresentationStyle中有一个枚举类型:.overFullScreen,这个方式的作用就是保证完成present动作后,控制器A的view依然保持在视图层级中。

所以我们设置控制器B的.modalPresentationStyle = .overFullScreen,测试证明这个属性可以保证完成present动作后,控制器A的view依然保持在视图层级中,但是重力感应的方向不会发生改变。所以这个方案不可用。

解决方案2

既然系统没有可以使用的,那我们可以在presen完成后,自己手动把控制器A 的View插入到控制器BView的下边。有两种方式,

方式一:

将控制器A的view直接插入到UITransitionView内的控制器B的View下

// 方式一:将当前控制器的view插入到 横屏view的下方

controller.view.superview?.insertSubview(strongSelf.view, belowSubview: controller.view)

方式二:

将window的rootViewController的View插入到Window之上,UITransitionView之下,这种方式的效果和.overFullScreen的效果一样。

这两种方式都可以,可以根据实际情况来选择使用

// 方式二:.overFullScreen的实际效果
if let keyWindow = UIApplication.shared.keyWindow,let rootViewController = UIApplication.shared.keyWindow?.rootViewController, let containerView = controller.view.superview  {
    keyWindow.insertSubview(rootViewController.view, belowSubview: containerView)
 }

方法2

自定义转场动画!

目前看来,腾讯视频有可能使用这个方式。

但是这个方式也有一个问题,就是自动转场动画后,从横屏返回竖屏,本该竖屏的控制器不能变回竖屏,这应该是苹果的一个bug,目前我的解决方式是在将要展现的生命周期方法中强行设置为正确的fram

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    print("Tabbar - WillAppear",view.frame)
    // 因为 presented 完成后,控制器的view的frame会错乱,需要每次将要展现的时候强制设置一下
    view.frame = UIScreen.main.bounds
}

demo

GitHub地址:iOSPlayerVerticalAndHorizontalScreenDemo

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值