How can I permanently show sidebar in a SwiftUI NavigationView or SplitNavigationView exactly like the Apple Settings App on iPad?
Asked Answered
P

4

7

I am trying to display a two column NavigationView in my app exactly like the settings on the iPad. With no way to collapse the sidebar on an iPad. I would have thought using a NavigationView with DoubleColumnStyle would work but it doesn't and it's deprecated. I can use a NavigationSplitView like before to control the initial look however the user is still able to collapse the navigation sidebar.

I thought there would be a simple solution to this but have been looking for a while and haven't found any approach that works.

So far I have the following:

struct SettingsView: View {
    
    @State private var columnVisibility = NavigationSplitViewVisibility.doubleColumn
    
    var body: some View {
        
        NavigationSplitView(columnVisibility: $columnVisibility) {
            Text("Sidebar")
        } detail: {
            Text("Detail")
        }
        
    }
}

Here both the icon in the top left to hide the sidebar is generated automatically and also dragging the sidebar to the left closes it.

Pakistan answered 30/1, 2023 at 11:3 Comment(2)
I have come across BalancedNavigationSplitViewStyle() which shows both sidebar and detail together but unfortunately it still allows the sidebar to collapse.Pakistan
Settings doesn't support multitasking split view because there isn't enough room for both columns) so I guess they didn't want to make that possible in SwiftUI. I think it was possible with the old NavigationView by overriding the size class with .environment(\.horizontalSizeClass, .regular) but I just checked and that has no effect on the new NavigationSplitView.Tuttle
G
9

Add add navigationSplitViewStyle balanced and also change columnVisibility to all

struct SettingsView: View {
    
    @State private var columnVisibility = NavigationSplitViewVisibility.all
    
    var body: some View {
        
        NavigationSplitView(columnVisibility: $columnVisibility) {
            Text("Sidebar")
        } detail: {
            Text("Detail")
        }
        .navigationSplitViewStyle(.balanced)
        
    }
}
Garvy answered 24/4, 2023 at 10:8 Comment(2)
This doesn't prevent clicking the Sidebar collapse icon to hide the sidebar.Valdovinos
did anyone get a solution to this?Chino
M
2

If you wan to prevent sidebar from collapsing, you can try .navigationSplitViewStyle(.balanced) modifier. Here is a full demo:

struct ContentView: View {
    
    @State private var columnVisibility =
    NavigationSplitViewVisibility.doubleColumn
    
    var body: some View {
        NavigationSplitView(columnVisibility: $columnVisibility){
            List(0..<30){ i in
                NavigationLink(destination: Text("Details of \(i)")) {
                    Text("id:\(i)")
                }

            } .navigationBarHidden(true)

        } detail: {
            Text("Choose an item from the content")
            
        }
        .navigationSplitViewStyle(.balanced) // this
    }
}

Prevent sidebar from collapsing

Meaningless answered 14/11, 2023 at 3:1 Comment(0)
D
2

You can get rid of the sidebar button by calling .toolbar(.hidden). This will get rid of the button but as well as the title from the sidebar. However, since the detail view also has a toolbar that shows the sidebar button, you can also call .toolbar(.hidden) on the detail view.

Unfortunately, this only works in landscape mode since in portrait mode, the sidebar can be opened and closed with a drag gesture from the left regardless of the bar being hidden or not.

@State private var columnVisibility = NavigationSplitViewVisibility.all

var body: some View {
    NavigationSplitView(columnVisibility: $columnVisibility) {
        HomeSidebarView()
            .toolbar(.hidden)
    } detail: {
       detailView
            .toolbar(.hidden)
    }
    .navigationSplitViewStyle(.balanced)
}

enter image description here

Drisko answered 23/6 at 22:22 Comment(0)
B
0

toolbar(removing:) was added with iOS 17.

NavigationSplitView {
    Text("Sidebar")
        .toolbar(removing: .sidebarToggle)
} detail: {
    Text("Detail")
}

Example

Benildas answered 19/8 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.