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.
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;-)
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
}
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.
playerLayer.videoGravity = AVLayerVideoGravityResizeAspectFit;
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
}
}
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.