2

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()
    
    }
}
}
  • 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 Rupprecht Jul 12 '20 at 14:14
  • I tried also .resizeAspect but it doesn't change anything, what do you mean exactly with set the autoresizingMask accordingly? @FrankSchlegel –  Jul 12 '20 at 16:05
  • 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 Rupprecht Jul 12 '20 at 16:12
  • 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 –  Jul 12 '20 at 20:28
  • @FrankSchlegel I actually found out where the problem was I'm gonna publish the answer below –  Jul 13 '20 at 00:11

1 Answers1

1

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

  • Hi.. I have exactly same issue. I applied your solution but didn't work. Can you please tell what changes you had to make to resolve the issue. It will be very helpful. – Sajib Ghosh Sep 17 '20 at 15:35