Is there any way to make NavigationSplitView's side bar with clear background?

1.4k views Asked by At

I am trying to make side bar in NavigationSplitView with clear background for side bar, so that detail view is visible under sidebar when it is open.In UIKit it is possible to make, when iPhone in portrait mode. How can I make it in SwiftUI? In view debugger I see under side bar hosting controller with white background which I do not know how to change.

enter image description here

Of course background of view which is for side bar is clear. I tried:

    struct ContentView: View { /* if iOS < 16 */
        var body: some View {
            NavigationView {
                SideView()
                MainView()
            }
        }
    }


    struct ContentView: View {  /* iOS 16 */
        var body: some View { 
            NavigationSplitView( sidebar: { SideView() },
                                 detail: { MainView() })
        }
    }

Also I have not found any information and explanation about such behaviour.In UIKit it was possible.If you know some information please explain or attach some links about this behaviour.

1

There are 1 answers

4
McCaffers On

You can achieve a transparent sidebar with Introspect using UIKit.

I've added a cyan colour to the detail view and used Introspect to make the view of the first ViewController (the sidebar) clear, and looped through all of the subviews to ensure the background is clear on them too.

import SwiftUI
import Introspect

struct ContentView: View {
    
    var body: some View {
        
        NavigationSplitView(
            sidebar: {
                NavigationLink(value: "Item 1") {
                    Text("Button").background(.white)
                }
            }, detail: {
                ZStack {
                    Color.cyan
                    Text("Main")
                }
            }
        )
        .background(.red)
        .introspectSplitViewController { controller in

            controller.viewControllers[0].view.backgroundColor = UIColor.clear
            
            for subview in controller.viewControllers[0].view.subviews {
                subview.backgroundColor = UIColor.clear
                for innerSubview in subview.subviews {
                    innerSubview.backgroundColor = UIColor.clear
                    for innerInnerSubview in innerSubview.subviews {
                        innerInnerSubview.backgroundColor = UIColor.clear
                    }
                }
            }
          }
        
    }
}

Screenshot of the result

Overlay

There is an overlay that appears over the detail view though, which I couldn't seem to remove. It looks to be controlled by part of the NavigationController. You'll see on the screenshot below.

I think this answer though should help you further along with the sidebar transparency. You can also avoid the overlay by using a different NavigationSplitViewstyleConfiguration https://developer.apple.com/documentation/swiftui/navigationsplitviewstyleconfiguration on the NavigationSplitView in SwiftUI, which pushes the detail view out of frame.

NavigationSplitView(
    sidebar: {
        NavigationLink(value: "Item 1") {
            Text("Button").background(.white)
        }
    }, detail: {
        ZStack {
            Color.cyan
            Text("Main")
        }
    }
)
.navigationSplitViewStyle(.balanced)

Use of Introspect

There are comments on Apple Forums on using Introspect for similar purposes: https://developer.apple.com/forums/thread/653489

A link to Introspect on Github, https://github.com/siteline/SwiftUI-Introspect

Hope that helps!