2
votes

I'm displaying a video inside a UIView, everything works fine and Video Layer Bounds are the same of the UIView in which it is embedded.

The problem is that the video is not displayed correctly inside the view's bounds, I can only see a part of it (precisely the center).

So I searched and found out that there's a property of AVPlayerLayer which is supposed to solve this problem: .videoGravity

I implemented it with .resizeAspectFill but it doesn't change anything.

Here is the code:

 class PlaceHolderVideoView : UIView{

  var player = AVPlayer()
  var playerLayer = AVPlayerLayer()
  let containerImageView = UIImageView(image: #imageLiteral(resourceName: "VideoContainerView"), contentMode: .scaleAspectFit)



override init(frame: CGRect) {
super.init(frame: frame)

setUpUI()

setUpPlayer()



}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

fileprivate func setUpUI(){
clipsToBounds = true
translatesAutoresizingMaskIntoConstraints = false

addSubview(containerImageView)
containerImageView.clipsToBounds = true
containerImageView.fillSuperview()


}

fileprivate func setUpPlayer(){

let urlPathString = Bundle.main.path(forResource: "dance", ofType: "mp4")

if let videoURL = urlPathString{
    
    let url = URL(fileURLWithPath: videoURL)
    player = AVPlayer(url: url)
    playerLayer = AVPlayerLayer(player: player)
    playerLayer.cornerRadius = 20
    playerLayer.bounds = self.containerImageView.bounds
    print(self.containerImageView.bounds)
    playerLayer.videoGravity = .resizeAspectFill
    
    
    self.layer.masksToBounds = true
    self.layer.cornerRadius = 20
    self.layer.addSublayer(playerLayer)
    
    player.play()
    
    }
}
}
1
Have you tried .resizeAspect? .resizeAspectFill is actually cropping the video to fill the layer, showing only the center part. Also, keep in mind that sublayers are not automatically resized when the parent layer's size changes. You need to set the autoresizingMask accordingly. - Frank Schlegel
I tried also .resizeAspect but it doesn't change anything, what do you mean exactly with set the autoresizingMask accordingly? @FrankSchlegel - user13370778
Oh sorry, just realized that layer autoresizingMask is only available on macOS. Then you need to update the bounds of playerLayer in layoutSubviews, e.g. by running playerLayer.bounds = self.containerImageView.bounds again. Otherwise, the playerLayer will not change size when its container changes size. - Frank Schlegel
Thanks for the suggestion @FrankSchlegel but I tried to set player layer bounds inside layoutSubviews method but it still doesn't change anything. I'm guessing there's some problem with the actual frame of the container view but I can't grasp where the issue is since I thought that layout subviews method was called when the subviews frame were already set - user13370778
@FrankSchlegel I actually found out where the problem was I'm gonna publish the answer below - user13370778

1 Answers

1
votes

To solve this problem I needed to call layoutSublayers method like this:

override func layoutSublayers(of layer: CALayer) {
    super.layoutSublayers(of: layer)
    
    playerLayer.frame = self.bounds
}

this method can set the bounds of the playerLayer correctly