Swift:调整 AVPlayerLayer 的大小以匹配其父容器的边界

Posted

技术标签:

【中文标题】Swift:调整 AVPlayerLayer 的大小以匹配其父容器的边界【英文标题】:Swift: Resize an AVPlayerLayer to match the bounds of its parent container 【发布时间】:2015-03-12 01:06:24 【问题描述】:

我有一个使用AVPlayerAVPlayerLayer(Swift,ios 8.2)播放的本地视频,当它的父视图(introView)调整大小时,我需要调整AVPlayerLayerintroPlayerLayer)的大小,包括方向变化。到目前为止,我尝试过的任何方法似乎都不起作用,而且 playerLayer 的大小和位置错误。

AVPlayer 使用本地 mp4 视频设置,AVPlayerLayer 使用该播放器初始化。然后将该层作为子层添加到父视图。

这是我的代码:

func playIntro() 
    let path = NSBundle.mainBundle().pathForResource("intro", ofType: "mp4")
    let url  = NSURL.fileURLWithPath(path!)
    let introPlayer           = AVPlayer(URL: url)
    introPlayer.allowsExternalPlayback = false

    var introPlayerLayer = AVPlayerLayer(player: introPlayer)
    introView.layer.addSublayer(introPlayerLayer)
    introPlayerLayer.frame = introView.bounds

    NSNotificationCenter.defaultCenter().addObserver(self, selector: "playerDidFinishPlaying:", name: AVPlayerItemDidPlayToEndTimeNotification, object: introPlayer.currentItem)

    introView.hidden = false
    introPlayer.play()

我应该将AVPlayerLayer 添加为UIView 的子层,还是应该将父容器(UIView) 子类化,如https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/Articles/02_Playback.html 的“播放器视图”部分所示。如果是这样,我将如何在 Swift 中编写 PlayerView 子类(在 Objective-C 中显示)? 提前感谢您的任何帮助。

【问题讨论】:

introPlayerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill :) @DeVladinci - 谢谢! 【参考方案1】:

斯威夫特 3.

private func playVideo() 
        guard let path = Bundle.main.path(forResource: "video", ofType:"mp4") else 
            debugPrint("video.m4v not found")
            return
        
        let player = AVPlayer(url: URL(fileURLWithPath: path))
        var playerLayer: AVPlayerLayer?
        playerLayer = AVPlayerLayer(player: player)
        playerLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
        playerLayer!.frame = self.view.frame
        self.view!.layer.addSublayer(playerLayer!)
        player.play()

    

【讨论】:

在使用子视图而不是主视图时甚至不显示我的播放器。 好答案。谢谢。【参考方案2】:

我想,在我自己的项目中,我能够做你想做的事情。这是没有子类化的。这是我的代码:

override func viewWillLayoutSubviews() 
   previewScene()


func previewScene() 
    var firstAsset: AVAsset!, secondAsset: AVAsset!, thirdAsset: AVAsset!


     firstAsset = MediaController.sharedMediaController.s3Shot1
     secondAsset = MediaController.sharedMediaController.s3Shot2
     thirdAsset  = MediaController.sharedMediaController.s3Shot3


    if firstAsset != nil && secondAsset != nil && thirdAsset != nil 
        let assets = [firstAsset, secondAsset, thirdAsset]
        var shots = [AVPlayerItem]()

        for item in assets 
            let shot = AVPlayerItem(asset: item)
            shots.append(shot)
        

        self.videoPlayer = AVQueuePlayer(items: shots)
        self.playerLayer = AVPlayerLayer(player: self.videoPlayer)
        self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill
         AVPlayerItemDidPlayToEndTimeNotification, object: self.videoPlayer.items().last)
        self.videoPreviewLayer.layer.addSublayer(playerLayer)
        self.playerLayer.frame = self.videoPreviewLayer.bounds

    


【讨论】:

videoPreviewLayer 是我的视图控制器内部的一个矩形视图。 @IBOutlet weak var videoPreviewLayer: UIView! 可以在这里给我建议:***.com/questions/54745359/…【参考方案3】:
introView.layer.masksToBounds = true

也可能有帮助

【讨论】:

你能扩展一下这个答案吗? ***.com/help/how-to-answer @RichBenner 我在让视频层保持在父层范围内时遇到问题。我使用self.playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFill 填充框架,但还需要masksToBounds = true 将其包含在父层的边界内。我不是经验丰富的 iOS 开发人员,但它对我有用。

以上是关于Swift:调整 AVPlayerLayer 的大小以匹配其父容器的边界的主要内容,如果未能解决你的问题,请参考以下文章

AVPlayerLayer 在 UIView 层中的位置

似乎无法获得 AVPlayerLayer 的视频高度

iOS Swift UIImage 调整大小影响性能的问题;调整大小时出现意外尺寸[重复]

禁用 UILabel、UIText 等的自动调整字体。在 iOS/Swift 中?

斯威夫特:如何在我的 AVPlayerLayer 顶部添加图像/文本以使其成为视频的一部分?

AVPlayerLayer