MPMoviePlayer setFullscreen function not working - swift - ios

I have a video stream in my app which i want to work like youtube player. It mean when the video player is in fullscreen and device is in landscape mode, on rotation to portrate, i want to set video player's fullscreen off. to do that i coded below:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
if toInterfaceOrientation == .Portrait
{
self.moviePlayer.setFullscreen(false, animated: true)
}
}
but when i rotate the device, it's still on fullscreen mode. how can i force movie player to exit fullscreen on orientation?

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return YES;
}

Related

iOS - keep layout in landscape but change controls

I'm done with the auto-layout stuff in my iOS universal App, and it's working perfectly in portrait. However, I want the user to be able to rotate the device and play the game in landscape mode. The problem I'm facing is that I don't want the layout to change at all, and only change the controls of the game (sliding up the screen should make the player go up in both orientations).
Thing is, I don't know how to prevent orientation from changing the layout and at the same time be able to change behaviour based on the orientation. Do you guys have any idea how I could manage that?
Did found a way to do, for future reference, when an orientation is disabled, we still can access device orientation (and not interface orientation), and register a notification to act upon change.
class ViewController: UIViewController {
var currentOrientation = 0
override func viewDidLoad() {
super.viewDidLoad()
// Register for notification about device orientation change
UIDevice.current.beginGeneratingDeviceOrientationNotifications()
NotificationCenter.default.addObserver(self, selector: #selector(deviceDidRotate(notification:)), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)
}
// Remove observer on window disappears
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
NotificationCenter.default.removeObserver(self)
if UIDevice.current.isGeneratingDeviceOrientationNotifications {
UIDevice.current.endGeneratingDeviceOrientationNotifications()
}
}
// That part gets fired on orientation change, and I ignore states 0 - 5 - 6, respectively Unknown, flat up facing and down facing.
func deviceDidRotate(notification: NSNotification) {
if (UIDevice.current.orientation.rawValue < 5 && UIDevice.current.orientation.rawValue > 0) {
self.currentOrientation = UIDevice.current.orientation.rawValue
}
}
}

How to rotate button when device orientation changes in swift?

How can I just rotate the buttons when my device is in portrait or landscape mode? I know something like that:
button.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
But where I have to call it up in my code?
I don't want to set my device in landscape mode, I just want to rotate the icons when it should be in landscape mode.
Thanks in advance!
You should override func
viewWillTransitionToSize(_ size: CGSize, withTransitionCoordinator coordinator:UIViewControllerTransitionCoordinator)
And call transform there
Don't forget to assign CGAffineTransformIdentity when rotated back
More about rotation: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIContentContainer_Ref/index.html#//apple_ref/occ/intfm/UIContentContainer/viewWillTransitionToSize:withTransitionCoordinator:
The best way to do this is viewDidLoad add this line of code bellow:
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(rotate), name: UIDeviceOrientationDidChangeNotification, object: nil)
and then in function rotate in case of device orientation do some code like this:
func rotate(){
if UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation) {
//your code here in landscape mode
}
if UIDeviceOrientationIsPortrait(UIDevice.currentDevice().orientation){
//your code in portrait mode
}
}
this solution is simple and really easy to do.
I guess you know how to "rotate" the buttons already, so I'll just tell you how to know that the device has rotated.
In a view controller, override willRotateToInterfaceOrientation:
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
}
In the method body, you can check the value of toInterfaceOrientation to know which orientation the device is rotating to. For example:
switch toInterfaceOrientation {
case Portrait:
// some code here...
default:
break
}

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

iOS: AVPlayerViewController enable fullscreen rotation in portrait oriented application

I have a UIViewcontroller, which contains a AVPlayerViewController with AVPlayer.
I want to enable rotation for AVPlayerViewController(when video is on fullscreen) and disable any rotation for UIViewController.
How can I enable rotation only for videos(on fullscreen) in my app?
Swift 2.2
In AppDelegate to allow rotation for player:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
guard let vc = (window?.rootViewController?.presentedViewController) else {
return .Portrait
}
if (vc.isKindOfClass(NSClassFromString("AVFullScreenViewController")!)) {
return .AllButUpsideDown
}
return .Portrait
}
Than create and use subclass of AVPlayerViewController for back to portrait mode when player exit full screen mode:
class YourVideoPlayer: AVPlayerViewController {
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if view.bounds == contentOverlayView?.bounds {
UIDevice.currentDevice().setValue(UIInterfaceOrientation.Portrait.rawValue, forKey: "orientation")
}
}
For me this was better. Just extend AVPlayerViewController :
import AVKit
import UIKit
class AVPlayerViewControllerRotatable: AVPlayerViewController {
override var shouldAutorotate: Bool {
return true
}
}
Swift 4
You have to enable the allowable rotations at the project level and then restrict rotation on all the viewControllers you DON'T want to rotate. i.e. if you have 5 viewControllers, you'll need to restrict rotation on 4 of them and only allow rotation on the Player Controller. You can see more on this here Handling autorotation for one view controller in iOS7

Camera orientation is not changed

I tried this code for scanning barcode:
https://www.hackingwithswift.com/example-code/media/how-to-scan-a-barcode
but it have a bug, when i change orientation of device, camera always has a Protrait orientation...
Any ideas how to fix this ?
I tried to change orientations in this method:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .Portrait
}
But it not helps.
For a camera to change the orientation you don't want to use that function. Do this instead...
previewLayer!.connection?.videoOrientation = AVCaptureVideoOrientation.Portrait
What this does is when the camera layer is created it sets the orientation.

Resources