How to change position of AVPlayer when changing orientation to lanscape mode in Swift

67 Views Asked by At

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.

landscape mode enter image description here

As well as CAGradientLayer, because it also ignores the constraints of its superview.

enter image description here

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)
        ])
    }
}

}

0

There are 0 best solutions below