2

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.

lorem ipsum
  • 21,175
  • 5
  • 24
  • 48

1 Answers1

1

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!

McCaffers
  • 46
  • 3
  • But could you please explain why it is not possible to het this behaviour like in UIKit?Apple suggests not to do this? – Анна Овчинникова Dec 18 '22 at 15:23
  • I couldn't find any functions on the NavigationSplitView to make the background of the underlying view transparent in SwiftUI. It looks to only be possible when using Introspect and changing the UIViewController View. From Github: Introspect is does not use any private API. It only inspects the view hierarchy using publicly available methods. I'm not sure on the comment about 'Apple suggests not to do this'. Apple documentation says you can use UIKit and SwiftUI together https://developer.apple.com/documentation/uikit (3rd Paragraph) – McCaffers Dec 18 '22 at 16:28
  • Do you mean to use Spit controller from UIKit and just wrap swiftUI views in it? – Анна Овчинникова Dec 18 '22 at 17:18
  • I originally looked at using Introspect to access the UIKit elements inside the SwiftUI view but that also would be an option (wrapping UIKit as a SwiftUI view). This page looks useful https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-modifiers-for-a-uiviewrepresentable-struct and Apples documentation https://developer.apple.com/documentation/swiftui/uiviewrepresentable – McCaffers Dec 18 '22 at 18:23