green8
green8

Reputation: 496

SwiftUI: How to force Landscape without AppDelegate

I am making app with Video Player in it and my whole struct is made for only portrait view, except this video player. I want to enable landscape rotation just for this view. But I've chacked lots of forums and every answere was to add some code to App Delegate, and i don't have it. What can i do then.

Upvotes: 9

Views: 10282

Answers (2)

Sergei Volkov
Sergei Volkov

Reputation: 1154

iOS 16 (and above)

Button("Force landscape") {
    guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
    windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape))
}

Upvotes: 6

Mahdi BM
Mahdi BM

Reputation: 2104

Here's a demo for you. You can change the orientation to the one you like by calling the function changeOrientation. You can also reverse an orientation change after it's done, using the .onReceive. The .onReceive is called every time there is an orientation change, so you can reverse a orientation change that you don't like.
I know this is not optimal, but this is the best i could find without using a lot of UIKit and AppDelegate. You can use AppDelegate for a better result (i think).

import SwiftUI
import UIKit

struct ContentView: View {
    
    private let rotationChangePublisher = NotificationCenter.default
        .publisher(for: UIDevice.orientationDidChangeNotification)
    @State private var isOrientationLocked = false
    
    var body: some View {
        VStack {
            Button("Change orientation") {
                if UIDevice.current.orientation.isPortrait {
                    changeOrientation(to: .landscapeLeft)
                } else {
                    changeOrientation(to: .portrait)
                }
            }.padding()
            
            Button("Orientation is \(isOrientationLocked ? "" : "NOT ")Locked to portrait-only") {
                isOrientationLocked.toggle()
            }.padding()
        }
        .font(.system(size: 17, weight: .semibold))
        .onReceive(rotationChangePublisher) { _ in
            // This is called when there is a orientation change
            // You can set back the orientation to the one you like even
            // if the user has turned around their phone to use another
            // orientation.
            if isOrientationLocked {
                changeOrientation(to: .portrait)
            }
        }
    }
    
    func changeOrientation(to orientation: UIInterfaceOrientation) {
        // tell the app to change the orientation
        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
        print("Changing to", orientation.isPortrait ? "Portrait" : "Landscape")
    }
}

Also, make sure you've allowed different orientations that you'd like to use, beforehand:

enter image description here

Upvotes: 7

Related Questions