iOS How to replicate Youtube App player rotation? - ios

Any idea about how the feature I show in this video is done?
It looks like the touch on the "expand" button force an orientation change for the device (infact when I swipe I'm pulling the control centre out).
Anyway only the video player seems to rotate. the scrollview underneath keeps its portrait orientation.

Looks like they're presenting the player controller with a custom segue animation, while having the player controller supporting only landscape.
Try presenting a view controller that has these implemented, like so:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
override func shouldAutorotate() -> Bool {
return false
}
Then the device should be in landscape. All you have left is to do the custom transition animation between the two and you're done.
From the docs:
preferredInterfaceOrientationForPresentation
If your view controller implements this method, your view controller’s
view is shown in the preferred orientation

Related

How can I enable rotation of screen programmatically in Swift?

I am have 3 VC and in Xcode I enabled only Portrait mode but for one VC need enable Landscape Left & Right mode.
How I can enabled these orientation programmatically?
I am try use this code but it's don't help me:
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .all
}
override open var shouldAutorotate: Bool {
return true
}
Also did try use next way:
Enable all screen orientation on xcode, and set for two VC only portrait mode, it's not bad BUT my VC have few subviews and when I hold phone in landscape orientation and then start program, VC have portrait orientation but other subview which I am create PROGRAMMATICALLY change self position on screen.
How I am can solve this problem?

Unlock orientation when viewing picture fullscreen

My UITableViewCell has a UIImageView in it. When the users taps on the UIImageView, an [IDMPhotoBrowser](https://github.com/ideaismobile/IDMPhotoBrowser) is presented from the UIImageView. The app is portrait only, however, when viewing the photo fullscreen in IDMPhotoBrowser, I'd like to give the user the ability to rotate to any orientation.
The IDMPhotoBrowser is presented on the UITableViewCell's delegate. The delegate is a regular UIViewController with a UITableView. The delegate is also a contained in a UINavigationController which is contained in a UITabBarController. I have tried many different solutions involving extending IDMPhotoBrowser and trying to add functions that add support for all orientations, I have tried presenting the IDMPhotoBrowser on the UITabBarController, the UINavigationController and the delegate UIViewController. I have also tried flipping a boolean located in the UITabBarController subclass that is then referenced in the function that asks for supported orientations, such that the supported orientations changes in relation to when the app presents the IDMPhotoBrowser. Nothing has worked.
The whole app needs to be constrained to only portrait orientation except for when the user is viewing an IDMPhotoBrowser or an AVPlayerViewController in fullscreen.
Make a UINavigationController parent class, inside your UINavigationController(parent) override these methods this way:
override func shouldAutorotate() -> Bool {
return true
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return self.topViewController.supportedInterfaceOrientations
}
in your VC you want to be rotated:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .All
}
in your VC you want NOT to be rotated:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return .AllButUpsideDown
}
Then push (or set as root VC etc) your Browser or Browser's parent VC in this navigation controller.

UINavigationController doesn't rotate when presenting child view controller

Here is my sample project
I have two view controllers embedded in a UINavigationController. On the first one, there is just a button performing a segue on the 2nd view controller. On the latter, a button dismiss it back to the 1rst view controller.
The 1rst view controller is not allowed to rotate and stays in Portrait while the 2nd is allowed to rotate in Landscape.
To do so, I added this code in the 1rst view controller:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
and added an extension to UINavigationController:
extension UINavigationController {
override public func shouldAutorotate() -> Bool {
if let topViewController = topViewController {
return topViewController.shouldAutorotate()
}
return false
}
override public func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if let topViewController = self.topViewController {
return topViewController.supportedInterfaceOrientations()
}
return .Portrait
}
}
On the 2nd view controller, I add programmatically a label with some autolayout constraints. The label's title show the UIDevice.currentDevice().orientation.
My problem is the following:
When I put the device on landscape when I'm on the 1rst view controller, it's fine, the layout is laid for Portrait but when I tapp the button to present the 2nd view controller, this one stays on Portrait instead of switching to Landscape.
And bigger problem for me as in my real project I set some constraints depending on the device orientation, the UIDevice.currentDevice().orientation return the Landscape position.
What's wrong? Is it a normal behaviour? How can I fix it?
In your sample project, you're not updating the label when the device is rotated. You should override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) Also, Apple recommends that you not use UIDevice orientation but rather just look at the bounds of your view controller's view. For example:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
if size.height<size.width {
label.text = "Landscape"
} else {
label.text = "Portrait"
}
}
Calling UIViewController.attemptRotationToDeviceOrientation() in the viewWillAppear of the 2nd view controller did the trick.

presentedViewController changes orientation of presenting view controller, breaks layout

I have a ViewController A that presents an MPMoviePlayerViewController. I want to force the video player to landscape, so I use this:
In the AppDelegate, supportedInterfaceOrientationsForWindow
if let viewController = self.window!.rootViewController?.presentedViewController {
if let playbackController = viewController as? MPMoviePlayerViewController {
return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
In my video player subclass, I set the supported orientation:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}
When the video player is closed in landscape, however, View Controller A is stuck in landscape. How do I prevent View Controller A from switching to landscape, and keep it in portrait?
Just add
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
to every view controller that needs it and avoid AppDelegate based orientation support.

Swift UIInterfaceOrientation for Multiple views

I have a navigation controller with multiple views. Most of the views are in portrait, and thus i lock it into portrait view by placing the following code in the Navigation View Controller
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientation.Portrait.toRaw()
}
This works just fine, and locks all my views in portrait orientation. However, This is 1 view that needs to only be in Landscape. If I use the code above, it locks my Landscape View, into portrait mode, and thus cutting off most of the view.
Can anybody help me out with what to use in the Landscape view controller to lock this particular View in landscape only.
I was using this, but it doesn't work.
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.toRaw())
}
override func shouldAutorotate() -> Bool{
// This method is the same for all the three custom ViewController
return true
}
For a small app, the solution I generally use is to have the navigation controller ask the view itself for it's rotation preference:
override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
Then, in each of your view controllers, you can override shouldAutorotate and and supportedInterfaceOrientations to give each controller the behavior you want.
One additional trick, to ensure that your view can rotate back to it's desired rotation, you can use this to to conditionally allow rotation back to portrait:
override func shouldAutorotate() -> Bool {
return !UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
}

Resources