When changing orientation to landscape, I try to adapt my programmatically created video player. Everything adapts normally through change of constraints, except for the player itself. He is not mobile. Probably, this is due to the fact that the player is added to the view as a Sublayer. I draw this conclusion because the buttons normally adapt along with the entire view (they are added on top of self.view above the player). AVPlayerLayer needs some other approach.
As well as CAGradientLayer, because it also ignores the constraints of its superview.
Here is my code. Here I configure the player itself:
class VideoPlayerView: UIView {
var m3u8Url: String
var player: AVPlayer?
init(frame: CGRect, videoUrl: String) {
self.m3u8Url = videoUrl
super.init(frame: frame)
setupVideoView()
setupGradientLayer()
}
func setupVideoView() {
if let url = URL(string: m3u8Url) {
let asset = AVURLAsset(url: url, options: nil)
let playerItem = AVPlayerItem(asset: asset)
player = AVPlayer(playerItem: playerItem)
let playerLayer = AVPlayerLayer(player: player)
self.layer.addSublayer(playerLayer)
playerLayer.frame = self.bounds
}
}
private func setupGradientLayer() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
gradientLayer.colors = [UIColor.clear.cgColor, UIColor.black.cgColor]
gradientLayer.locations = [0.7, 1.2]
controlsView.layer.addSublayer(gradientLayer)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
This is my VC with managing constraints:
class ViewController: UIViewController {
@IBOutlet weak var navigationView: UIView!
var playerContainerView = UIView()
var videoPlayerView: VideoPlayerView?
var url: String?
private var landScapeContainerTopConstraint: NSLayoutConstraint?
private var portraitContainerTopConstraint: NSLayoutConstraint?
private var landScapeContainerBottomConstraint: NSLayoutConstraint?
private var portraitContainerHeightConstraint: NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
setupPlayerContainerView()
addPlayerView()
}
private func setupPlayerContainerView() {
if let keyWindow = UIApplication.shared.keyWindow {
playerContainerView.backgroundColor = .black
playerContainerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(playerContainerView)
let height = keyWindow.frame.width * 9 / 16
landScapeContainerTopConstraint = playerContainerView.topAnchor.constraint(equalTo: view.topAnchor)
portraitContainerTopConstraint = playerContainerView.topAnchor.constraint(equalTo: navigationView.bottomAnchor)
landScapeContainerBottomConstraint = playerContainerView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
portraitContainerHeightConstraint = playerContainerView.heightAnchor.constraint(equalToConstant: height)
NSLayoutConstraint.activate([
playerContainerView.leftAnchor.constraint(equalTo: view.leftAnchor),
playerContainerView.rightAnchor.constraint(equalTo: view.rightAnchor),
])
}
updateContainerConstraints()
}
private func addPlayerView() {
if let videoURL = url?.replacingOccurrences(of: " ", with: "%20") {
videoPlayerView = VideoPlayerView(frame: playerContainerView.bounds, videoUrl: videoURL)
if let videoPlayerView = videoPlayerView {
playerContainerView.addSubview(videoPlayerView)
}
}
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
updateContainerConstraints()
}
private func updateContainerConstraints() {
if UIDevice.current.orientation.isLandscape {
landScapeContainerTopConstraint?.isActive = true
portraitContainerTopConstraint?.isActive = false
landScapeContainerBottomConstraint?.isActive = true
portraitContainerHeightConstraint?.isActive = false
// activate VideoPlayerView constraints
updatePlayerConstraints()
} else {
landScapeContainerTopConstraint?.isActive = false
portraitContainerTopConstraint?.isActive = true
landScapeContainerBottomConstraint?.isActive = false
portraitContainerHeightConstraint?.isActive = true
}
}
func updatePlayerConstraints() {
videoPlayerView?.translatesAutoresizingMaskIntoConstraints = false
if let videoPlayerView = videoPlayerView {
NSLayoutConstraint.activate([
videoPlayerView.topAnchor.constraint(equalTo: playerContainerView.topAnchor),
videoPlayerView.leftAnchor.constraint(equalTo: playerContainerView.leftAnchor),
videoPlayerView.rightAnchor.constraint(equalTo: playerContainerView.rightAnchor),
videoPlayerView.bottomAnchor.constraint(equalTo: playerContainerView.bottomAnchor)
])
}
}
}


