Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AVPlayer force landscape mode for fullscreen

I am playing a video using an AVPlayer which is about 320x200 frame in my app. The avplayer also has a custom 'fullscreen' button added as overlay, like the youtube app player. How can I implement it such that when the app is in portrait mode and the user clicks fullscreen button, the video will rotate to fullscreen but in landscape mode? I tried using transform and it works partially, because when its in fullscreen mode, if user switches device to portrait orientation; the avplayer frame changes abruptly. I want it to work like the youtube app i.e. when in fullscreen mode, it should stay so even if user rotates device. Only should return to original size when turn off fullscreen. I don't want to use avplayerviewcontroller due to design of the app. Thanks in advance for help.

like image 701
King David Avatar asked Dec 11 '22 16:12

King David


2 Answers

Great question! Allowing the AVPLayerLayer to go fullscreen is important. A considerable amount of app configuration for a single view to handle both portrait and landscape, just to display a full screen video? Please.

Transforms and frame manipulation can solve this issue:

extension CGAffineTransform {

    static let ninetyDegreeRotation = CGAffineTransform(rotationAngle: CGFloat(M_PI / 2))
}

extension AVPlayerLayer {

    var fullScreenAnimationDuration: TimeInterval {
        return 0.15
    }

    func minimizeToFrame(_ frame: CGRect) {
        UIView.animate(withDuration: fullScreenAnimationDuration) {
            self.setAffineTransform(.identity)
            self.frame = frame
        }
    }

    func goFullscreen() {
        UIView.animate(withDuration: fullScreenAnimationDuration) {
            self.setAffineTransform(.ninetyDegreeRotation)
            self.frame = UIScreen.main.bounds
        }
    }
}

Setting the frame of the AVPlayerLayer changes it's parent's frame. Save the original frame in your view subclass, to minimize the AVPLayerLayer back to where it was. This allows for autolayout.

IMPORTANT - This only works if the player is in the center of your view subclass.

Incomplete example:

class AVPlayerView: UIView {

    fileprivate var avPlayerLayer: AVPlayerLayer {
        return layer as! AVPlayerLayer
    }

    fileprivate var hasGoneFullScreen = false
    fileprivate var isPlaying = false
    fileprivate var originalFrame = CGRect.zero

    func togglePlayback() {
        if !hasGoneFullScreen {
            originalFrame = frame
            hasGoneFullScreen = true
        }

        isPlaying = !isPlaying
        if isPlaying {
            avPlayerLayer.goFullscreen()
            avPlayerLayer.player?.play()
        } else {
            avPlayerLayer.player?.pause()
            avPlayerLayer.minimizeToFrame(originalFrame)
        }
    }
}
like image 158
Eric Armstrong Avatar answered Dec 23 '22 23:12

Eric Armstrong


In my opinion, you should create a FullScreenViewController, which is forced always supporting landscape. Then present that view controller from your current one when press "fullscreen" button and also pass AVPlayer instance to it, then set frame for AVPlayerLayer and resume playing. After dismissing, it would be back to normal, I mean your "portrait" mode.

like image 45
HSG Avatar answered Dec 23 '22 23:12

HSG