On app launch, I want to get the horizontalSizeClass and based on if it's compact or regular, apply a navigation style to my root navigation view like so:
import SwiftUI
@main
struct MyApp: App {
@Environment(\.horizontalSizeClass) var sizeClass
var body: some Scene {
WindowGroup {
if sizeClass == .compact {
NavigationView {
Text("Compact size class inside stack navigation style")
}
.navigationViewStyle(StackNavigationViewStyle())
} else {
NavigationView {
Text("Regular size class inside default navigation style")
}
}
}
}
}
However, sizeClass
always returns nil
in this case.
How do I
- determine if the horizontal size class is compact or regular on the root view, and
- make the navigation style adapt to the size class any time it changes
My app is targeting iOS 14 for both iPhone and iPad.
Any help or a different approach to adapt for size class changes for the whole app is much appreciated.
Update 1
I tried the suggestions to use a ViewModifier
or creating a custom view and adding the navigation in it's body like so:
import SwiftUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
MyRootView()
}
}
}
struct MyRootView: View {
@Environment(\.horizontalSizeClass) var sizeClass
var body: some View {
if sizeClass == .compact {
NavigationView {
Text("Compact size class inside stack navigation style")
}
.navigationViewStyle(StackNavigationViewStyle())
} else {
NavigationView {
Text("Regular size class inside default navigation style")
}
}
}
}
However, the navigation stack pops to the root view every time the sizeClass
changes. Is there a way to preserve the stack? For example: If the user is 5 levels deep in navigation, and sizeClass
changes, change the navigation style while keeping the visible screen?
Thank you!
Update 2
I was able to find a WWDC session explaining exactly what I want, but it's in UIKit.
See 18:35 here: https://developer.apple.com/wwdc20/10105
I'm trying to achieve the same goal in SwiftUI (keep the screen the user selected while changing the size class to compact).
According to the session, UISplitViewController
supports this because there's the concept of Restorable
and Restore
in the detail view. I can't find a way to do this in SwiftUI.