I want to keep a portrait orientation even if user rotate the phone. At the same time, I want to change the orientation with a button.
If I put only portrait as supported orientation in plist and then rotate, application gives me error. If I put all the supported orientation but shouldAutorotate method to NO, Application crashes.
So, basically as I can see I can only support multiple orientation if I let the application to autorotate.
Can I achieve what I need?
shouldAutorotate
this is a get-only property.
what you can do is:
override var shouldAutorotate: Bool {
return false
}
Maybe this is also interesting for you: how to dissable and enable auto rotate on swift?
May be the following line of code will work for you. set orientation programmatically.
In your Appdelegate class write this code:
var orientationLock = UIInterfaceOrientationMask.all
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return self.orientationLock
}
2.Make custom helper class as follows:
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
/// OPTIONAL Added method to adjust lock and rotate to the desired orientation
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
then use it in your desire viewcontroller like:
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
AppUtility.lockOrientation(.portrait)
// Or to rotate and lock
// AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
}
override func viewWillDisappear(_ animated: Bool){
super.viewWillDisappear(animated)
// Don't forget to reset when view is being removed
AppUtility.lockOrientation(.all)
}
note: keep remember Require Full Screen option is checked from target settings.
Related
I have 2 viewcontrollers (A & B).
A is auto rotation and B is force to landscape.
When user turn off Portrait Orientation Lock, it's work ok : A always rotation follow device orientation.
But when Portrait Orientation Lock is on, A's orientation is always landscape when it is returned from B.
How to force A is always portrait when Portrait Orientation Lock is enable.
Thanks.
Here - https://stackoverflow.com/a/41811798/10261915 You have answer
Add this to AppDelegate
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
/// OPTIONAL Added method to adjust lock and rotate to the desired orientation
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
}
}
and use for example
AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
add to BViewController :
override func viewDidLoad() {
super.viewDidLoad()
UIDevice.current.setValue(Int(UIInterfaceOrientation.landscapeLeft.rawValue), forKey: "orientation")
}
override func viewWillDisappear(_ animated: Bool) {
UIDevice.current.setValue(Int(UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")
}
I am trying to make just one view of the landscape and other all views are on the portrait. It works but there is an issue on every second-time screen doesn't rotate at all.
Here is the scenario that I am talking about:
On every second time, device rotation doesn't work.
Here is my code
AppDelegate.swift
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return .portrait
}
Controller1.swift
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .portrait
}
override var shouldAutorotate: Bool {
return true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
AppUtility.lockOrientation(.portrait)
}
DetailController.swift
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
AppUtility.lockOrientation(.landscape, andRotateTo: .landscapeLeft)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if isMovingFromParentViewController {
AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
}
}
Code that effects the rotation
struct AppUtility {
static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
if let delegate = UIApplication.shared.delegate as? AppDelegate {
delegate.orientationLock = orientation
}
}
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
So, How to force rotate detail view every time it loads?
Step 1:- Please define a below-mentioned variable in app delegate.
var shouldRotate : Bool = false
Step 2:- Implement the following delegate method as below.
//MARK:- Set Device Orientation Delegate Method
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return shouldRotate ? .landscapeRight : .portrait
}
Step 3 :- Define constant class and add "Set Portrait Orientation" and "Set Landscape Right Orientation" function in the class.
//MARK:- Set Portrait Orientation
func setPortraitOrientation() {
appDelegateInstance.shouldRotate = false
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
}
//MARK:- Set Landscape Right Orientation
func setLandscapeRightOrientation() {
appDelegateInstance.shouldRotate = true
UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
}
Step 4:- Use the following code in your class (Target landscape class)
Step 4.1:- In view will appear call set Landscape Right Orientation function shown below.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
setLandscapeRightOrientation()
}
Step 4.2 :- When you leave the screen implement the following code in the action.
//MARK:- Left Bar Button Tapped Delegate Method
func leftBarButtonTapped() {
_ = self.navigationController?.popViewController(animated: false)
setPortraitOrientation()
}
Happy Coding! Cheers!!
I've got an Objetive-C app delegate that is part of a project I'm interfacing with my own. I'm attempting to lock orientation, but it looks like the old methods (below) no longer work. Setting the orientation in viewDidLoad rotates the screen but allows the user to rotate back to portrait. I've attempted converting to "override var" but no luck. The current solutions (link below) look to all involve an app delegate call, but I cannot locate the solution for a Swift call to an Objective C app delegate.
How to lock orientation of one view controller to portrait mode only in Swift
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscapeRight
}
To force only one controller to be at landscape orientation.
Manager:
class OrientationManager {
static let shared = OrientationManager()
/// you can set any orientation to lock
var orientationLock = UIInterfaceOrientationMask.portrait
/// lock orientation and force to rotate device
func lock(for orientation: UIInterfaceOrientationMask, rotateTo rotateOrientation: UIInterfaceOrientation) {
orientationLock = orientation
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}
}
Usage:
1) Add code to AppDelegate
func application(_ application: UIApplication,
supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return OrientationManager.shared.orientationLock
}
2) Use in controller
open class LandscapeController: UIViewController {
/// orientation for one controller
override open func viewDidLoad() {
super.viewDidLoad()
OrientationManager.shared.lock(for: .landscape, rotateTo: .landscapeLeft)
}
/// set previous state of orientation or any new one
override open func viewWillDisappear(_ animated : Bool) {
super.viewWillDisappear(animated)
OrientationManager.shared.lock(for: .portrait, rotateTo: .portrait)
}
}
Solved my problem using this link, after trying just about everything.
how to lock portrait orientation for only main view using swift
I utilized the answer from JasonJasonJason and updated the code to get rid of the ->.
The below code went in my first VC
extension UINavigationController {
override open var shouldAutorotate: Bool {
return true
}
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return (visibleViewController?.supportedInterfaceOrientations)!
}
}
Then subsequent VCs
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscape
}
Then since I had a TabBarController, I added this to the controller that pushes to the tab view. If you try to re-use the initial UINavigationController extension it won't let you, but the TabBarController ignores it. So the below extension solves it for any VC's with the TabBar
extension UITabBarController {
override open var shouldAutorotate: Bool {
return true
}
override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.landscape
}
}
For xcode 8.x & swift 3.x
We can control device orientation for particular screen.
On AppDelegate.swift make a variable enableAllOrientation:
var enableAllOrientation = false
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if (enableAllOrientation == true){
return UIInterfaceOrientationMask.all
}
return UIInterfaceOrientationMask.portrait
}
& mask for particular view controller as -
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.enableAllOrientation = false
}
I have an app where all the views are portraits but only one view which is a UIWebView which loads a PDF needs to be in Landscape.
My project settings are below:
I have tried the following:
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
let orientation: UIInterfaceOrientationMask = [UIInterfaceOrientationMask.Landscape, UIInterfaceOrientationMask.LandscapeLeft]
return orientation
}
The above code does not seem to be working. I got the code by searching online. I am not sure what I am doing wrong. Any suggestions would be help and if you can provide some sample code would be great.
I just want to force landscape orientation for one UIWebView.
EDIT:
Error:
If its hard to read here is the error:
Supported orientations has no common orientation with the application, and [KM_T_World.MainViewController shouldAutorotate] is returning YES'
Implement this in your View Controller:
override func viewDidLoad() {
super.viewDidLoad()
UIViewController.attemptRotationToDeviceOrientation()
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return [UIInterfaceOrientationMask.LandscapeLeft, UIInterfaceOrientationMask.LandscapeRight]
}
Use this code:
override func viewDidAppear(animated: Bool) {
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
And your Device orientation should be:
Result:
Sample for more Info.
UPDATE:
It is simple to lock orientation for particular view by adding this code:
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask{
return UIInterfaceOrientationMask.Portrait
}
Is it possible to enable/disable rotation parameter for current screen or this property is for all application?
Sure:
- (BOOL)shouldAutorotate
{
return YES;
}
- (NSUInteger)supportedInterfaceOrientations
{
//Choose your available orientation, you can also support more tipe using the symbol |
//e.g. return (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight)
return (UIInterfaceOrientationMaskPortrait);
}
If you have multiple ViewControllers within a NavigationController, and you wish to disable rotation in one of them only, you need to set and control rotation within ApplicationDelegate. Here is how to do it in Swift...
In AppDelegate.swift:
class AppDelegate: UIResponder, UIApplicationDelegate {
var blockRotation: Bool = false
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
if (self.blockRotation) {
println("supportedInterfaceOrientations - PORTRAIT")
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
} else {
println("supportedInterfaceOrientations - ALL")
return Int(UIInterfaceOrientationMask.All.rawValue)
}
}
In the ViewController that you want to block rotation, add UIApplicationDelegate to your class...
class LoginViewController: UIViewController, UITextFieldDelegate, UIApplicationDelegate {
and then create a reference to the AppDelegate...
var appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
In viewDidLoad, set appDelegate.blockRotation = true:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
appDelegate.blockRotation = true
}
In viewWillAppear, set the orientation to force the device to the chosen orientation (Portrait in this example):
override func viewWillAppear(animated: Bool) {
let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
Then in viewWillDisappear, or in prepareForSegue, set appDelegate.blockRotation = false:
override func viewWillDisappear(animated: Bool) {
appDelegate.blockRotation = false
}
This will block rotation in the one view controller within a Navigation Controller that contains multiple ViewControllers. Hope this helps.