I have a custom UITableViewCell
that displays either an image or a video. If there's a video, it initially downloads and displays the thumbnail from that video while the video is loading and preparing to play.
It all works, the problem is that I get the ratio of the thumbnail, store it in the database and when I download the thumbnail, it makes the height based on that ratio. It works great for images. But the issue is that the AVPlayerLayer
frame doesn't cover the entire thumbnail and it looks like this:
Here's how I do it:
func updateView() {
if let videoUrlString = post?.videoUrl, let videoUrl = URL(string: videoUrlString) {
volumeView.isHidden = false
player = AVPlayer(url: videoUrl)
playerLayer = AVPlayerLayer(player: player)
playerLayer!.frame = postImageView.frame // thumbnail image
playerLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill
contentView.layer.addSublayer(playerLayer!)
self.volumeView.layer.zPosition = 1
layoutIfNeeded()
player?.play()
player?.isMuted = videoIsMuted
}
if let ratio = post?.ratio {
photoHeightConstraint.constant = UIScreen.main.bounds.width / ratio
layoutIfNeeded()
}
}
I'm not doing something right apparently or I'm missing something based on my final result. Any clue?
UPDATE:
I notice that if you scroll the cells slowly, the video is being displayed according to the size of the thumbnail. But if you scroll fast, it mismatches the frame. I assume it has something to do with reusability or it simply cannot catch up with the frame? Here's my code for prepareForReuse()
method:
override func prepareForReuse() {
super.prepareForReuse()
profileImageView.image = UIImage(named: "placeholder")
postImageView.image = UIImage(named: "profile_placeholder")
volumeView.isHidden = true
if let p = player, let pLayer = playerLayer {
p.pause()
pLayer.removeFromSuperlayer()
}
}
The solution turned out to be rather simple. Basically each post contains either post or a video, but either way, it always contains an image. I also set the ratio
of that image (the width
devided by the height
). So, all I had to do is set the player's width
to the screen width devided by the ratio and it gives your the proper frame.
playerLayer.frame.size.height = UIScreen.main.bounds.width / postRatio