AVPlayer layer inside a view does not resize when UIView frame changes

前端 未结 13 786
小蘑菇
小蘑菇 2020-12-23 17:08

I have a UIView which contains an AVPlayer to show a video. When changing orientation, I need to change the size and location of the video.

<
相关标签:
13条回答
  • 2020-12-23 17:32

    Actually you shouldn't add AVPlayer's layer as a sublayer. Instead of that you should use the following method, in the subclass of view in which you want to display AVPlayer.

    + (Class)layerClass
    {
         return [AVPlayerLayer class];
    }
    

    And use the following line to add(set) the player layer.

    [(AVPlayerLayer *)self.layer setPlayer:self.avPlayer];
    

    Hope it helps;-)

    0 讨论(0)
  • 2020-12-23 17:33

    Found a great article by Marco Santarossa that shows multiple approaches to fixing. https://marcosantadev.com/calayer-auto-layout-swift/

    I used his first suggestion to reset the layer frame during viewDidLayoutSubViews() event.

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        playerLayer.frame = view.layer.bounds
    }
    
    0 讨论(0)
  • 2020-12-23 17:36

    theDunc's answer did not work for me. I found a solution that is more simple: I just needed to adjust the frame of the AVPlayerLayer after changing it in the UIView:

    avPlayerLayer.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    

    In this blog is stated, that a View's frame also affect that of the layer in it.

    When you change a view’s frame, it’s simply changing the layer’s frame.

    For this case, it is not true.

    0 讨论(0)
  • 2020-12-23 17:37
      playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
    
    0 讨论(0)
  • 2020-12-23 17:37

    To get to playerLayer, you need to loop through videoHolderView.layer.sublayers and change each one.

    this is what I did in Swift 2.2

    if let sublayers = videoHolderView.layer.sublayers{
        for layer in sublayers where layer is AVPlayerLayer{
            layer.frame.size = ... // change size of the layer here
        }
    }
    
    0 讨论(0)
  • 2020-12-23 17:41

    Converting @Suran's solution to Swift:

    First, create a class inheriting UIView where you override only 1 variable:

    import UIKit
    import AVFoundation
    
    class AVPlayerView: UIView {
        override class var layerClass: AnyClass {
            return AVPlayerLayer.self
        }
    }
    

    Then add a simple UIView using the interface builder and change its class to the one you just created: AVPlayerView

    Then, make an outlet for that view. Call it avPlayerView

    @IBOutlet weak var avPlayerView: AVPlayerView!
    

    Now, you can use that view inside your viewcontroller and access its avlayer like this:

    let avPlayer = AVPlayer(url: video)
    let castedLayer = avPlayerView.layer as! AVPlayerLayer
    castedLayer.player = avPlayer
    avPlayer.play()
    

    The layer will now follow the constraints just like a regular layer would do. No need to manually change bounds or sizes.

    0 讨论(0)
提交回复
热议问题