AVPlayer强制横屏模式全屏播放

4

我正在使用AVPlayer在我的应用程序中播放一个大约320x200帧的视频。AVPlayer还有一个自定义的“全屏”按钮作为覆盖层,就像YouTube应用程序播放器一样。如何实现当应用程序处于竖屏模式且用户点击全屏按钮时,视频将旋转到横屏模式的全屏状态?我尝试使用transform并且它部分地起作用,因为当它处于全屏模式时,如果用户将设备切换到纵向方向,则avplayer框架会突然更改。我想让它像YouTube应用程序一样工作,即当处于全屏模式时,即使用户旋转设备,它也应保持不变。只有在关闭全屏模式时才返回到原始大小。由于应用程序的设计,我不想使用AVPlayerViewController。谢谢提前帮助。


1
当视频正在播放并且全屏时,将 supportedInterfaceOrientations 设置为仅横向。 - William GP
这与下面给出的答案配合使用,您能否也看到我对其关闭全屏实现问题的评论? - King David
澄清一下:您的问题是当您关闭全屏播放器时,较小的播放器不知道如何继续播放和从哪里开始? - William GP
如果是这样,请尝试通过“unwindSegue”传递变量作为可能的解决方案。 - William GP
@WilliamGP 好的,我只是将视频容器视图重新添加为呈现视图的子视图,它可以正常工作... 但是叠加控件不再显示。有什么想法可能会发生什么? - King David
显示剩余2条评论
2个回答

9
很好的问题!允许AVPlayerLayer全屏非常重要。为了显示全屏视频,让一个视图同时处理竖屏和横屏的大量应用程序配置?不需要这样做。
使用转换和框架操作可以解决此问题:
extension CGAffineTransform {

    static let ninetyDegreeRotation = CGAffineTransform(rotationAngle: CGFloat(M_PI / 2))
}

extension AVPlayerLayer {

    var fullScreenAnimationDuration: TimeInterval {
        return 0.15
    }

    func minimizeToFrame(_ frame: CGRect) {
        UIView.animate(withDuration: fullScreenAnimationDuration) {
            self.setAffineTransform(.identity)
            self.frame = frame
        }
    }

    func goFullscreen() {
        UIView.animate(withDuration: fullScreenAnimationDuration) {
            self.setAffineTransform(.ninetyDegreeRotation)
            self.frame = UIScreen.main.bounds
        }
    }
}

设置AVPlayerLayer的框架会改变其父视图的框架。在您的视图子类中保存原始框架,将AVPLayerLayer最小化到其原始位置。这样可以实现自动布局。

重要提示-只有当播放器位于视图子类的中心时,此方法才有效。

示例不完整:

class AVPlayerView: UIView {

    fileprivate var avPlayerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    fileprivate var hasGoneFullScreen = false
    fileprivate var isPlaying = false
    fileprivate var originalFrame = CGRect.zero

    func togglePlayback() {
        if !hasGoneFullScreen {
            originalFrame = frame
            hasGoneFullScreen = true
        }

        isPlaying = !isPlaying
        if isPlaying {
            avPlayerLayer.goFullscreen()
            avPlayerLayer.player?.play()
        } else {
            avPlayerLayer.player?.pause()
            avPlayerLayer.minimizeToFrame(originalFrame)
        }
    }
}

4

我认为,你应该创建一个FullScreenViewController,并强制支持横屏。然后在当前视图控制器中按下“全屏”按钮时,从当前视图控制器呈现FullScreenViewController并将AVPlayer实例传递给它,然后为AVPlayerLayer设置框架并恢复播放。关闭后,将回到正常状态,也就是“纵向”模式。


这也是我想到的一个可能的解决方案。希望看看是否还有其他方法。 - King David
我尝试了使用FullScreenViewController的解决方案,并传递了包含AVPlayerLayer以及自定义控件UIView的容器UIView。到目前为止一切都很好。但是,当点击关闭全屏时,我会解除FullScreenViewController,然而播放器不会在我的呈现视图中播放。我该如何在FullScreenViewController中实现关闭全屏?因为我认为它被解除后,它的视图即播放器容器视图被释放了。 - King David
一些代码:FullScreenViewController *controller = [[FullScreenViewController alloc] init]; controller.view = self.playerContainer; // 容器 uiview [self presentViewController:controller animated:YES completion:nil]; - King David
好的,我只是在将视频容器视图重新添加为呈现视图的子视图,它就可以正常工作了。然而,叠加控件视图不再显示。您有什么想法会发生什么? - King David
如果您正在使用自定义视图来呈现视频,则不再支持内置控件,您必须创建自己的UI控件,例如控制底部栏和标题栏。 - HSG
是的,我正在做这件事。AVPlayer已添加为videoContainer视图的子层,UI控件已添加为videoContainer的子视图。然而,在退出全屏后,控件不显示。 - King David

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接