简体   繁体   中英

Force landscape orientation in one View

In my App all Views are forced to portrait orientation via info.plist.

The exception should be "MyView" which should always be in landscape orientation.

What I did after taking a deeper look in SO:

Added in AppDelegate.swift:

static var orientationLock = UIInterfaceOrientationMask.portrait 

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return AppDelegate.orientationLock
}

MyView.swift

struct MyView: View {
var body: some View {
    ZStack {
        // ...Some Images, etc.
    }
    .onAppear(perform: orientationLandscape)
    .onDisappear(perform: orientationPortrait)
}

func orientationLandscape() {
    AppDelegate.orientationLock = UIInterfaceOrientationMask.landscapeRight
    UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight, forKey: "orientation")
    UINavigationController.attemptRotationToDeviceOrientation()
}

func orientationPortrait() {
    AppDelegate.orientationLock = UIInterfaceOrientationMask.portrait
    UIDevice.current.setValue(UIInterfaceOrientation.portrait, forKey: "orientation")
    UINavigationController.attemptRotationToDeviceOrientation()
}

}

UIDevice.current.setValue produces an error. Without that line I can change the orientation in MyView manually by holding the device in landscape/portrait but it should switch automatically when opening and closing the View.

I solved this by orientating on bmjohns answer on a similar question:

  1. Add some code in AppDelegate (this part i had already)
  2. Make a struct and func which does the job (small adjustments for XCode 11 and SwiftUI were needed)
  3. Execute the func onAppear of your View

there is a way for Force landscape orientation

Put the code in viewDidLoad()

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")

and also,

override var shouldAutorotate: Bool {
    return true
}

for SwiftUI

We set the project orientation to only support Portrait mode.

Then in your AppDelegate add an instance variable for orientation and conform to the supportedInterfaceOrientationsFor delegate method.

static var orientationLock = UIInterfaceOrientationMask.portrait

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return AppDelegate.orientationLock
}

Then when your about to present your landscape view perform the following actions:

AppDelegate.orientationLock = UIInterfaceOrientationMask.landscapeLeft
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

And on dismissal,

AppDelegate.orientationLock = UIInterfaceOrientationMask.portrait
UIDevice.current.setValue(UIInterfaceOrientation.portrait, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

Hope this will help you ...:)

Since some info is missing on accepted answer i will put what i used in Swift 5

class AppDelegate: UIResponder, UIApplicationDelegate {


    var orientationLock = UIInterfaceOrientationMask.portrait

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return orientationLock
    }
}

struct AppUtility {

    static func orientationLandscape() {
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
                delegate.orientationLock = UIInterfaceOrientationMask.landscapeRight
        }
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
        UINavigationController.attemptRotationToDeviceOrientation()
    }
    
    static func orientationPortrait() {
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
                delegate.orientationLock = UIInterfaceOrientationMask.portrait
        }
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        UINavigationController.attemptRotationToDeviceOrientation()
    }

}

.onAppear(perform: {
            AppUtility.orientationLandscape()
        }).onDisappear(perform: {
            AppUtility.orientationPortrait()
        })

Opening a view

.fullScreenCover(isPresented: $isPresented) {
                                NavigationLazyView(aView())
                            }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM