I've got a super simple SwiftUI master-detail app:
import SwiftUI
struct ContentView: View {
@State private var imageNames = [String]()
var body: some View {
NavigationView {
MasterView(imageNames: $imageNames)
.navigationBarTitle(Text("Master"))
.navigationBarItems(
leading: EditButton(),
trailing: Button(
action: {
withAnimation {
// simplified for example
self.imageNames.insert("image", at: 0)
}
}
) {
Image(systemName: "plus")
}
)
}
}
}
struct MasterView: View {
@Binding var imageNames: [String]
var body: some View {
List {
ForEach(imageNames, id: \.self) { imageName in
NavigationLink(
destination: DetailView(selectedImageName: imageName)
) {
Text(imageName)
}
}
}
}
}
struct DetailView: View {
var selectedImageName: String
var body: some View {
Image(selectedImageName)
}
}
I'm also setting the appearance proxy on the SceneDelegate for the navigation bar's colour"
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.shadowColor = UIColor.systemYellow
navBarAppearance.backgroundColor = UIColor.systemYellow
navBarAppearance.shadowImage = UIImage()
UINavigationBar.appearance().standardAppearance = navBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
// Create the SwiftUI view that provides the window contents.
let contentView = ContentView()
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
Now, what I'd like to do is for the navigation bar's background colour to change to clear when the detail view appears. I still want the back button in that view, so hiding the navigation bar isn't really an ideal solution. I'd also like the change to only apply to the Detail view, so when I pop that view the appearance proxy should take over and if I push to another controller then the appearance proxy should also take over.
I've been trying all sorts of things:
- Changing the appearance proxy on didAppear
- Wrapping the detail view in a UIViewControllerRepresentable
(limited success, I can get to the navigation bar and change its colour but for some reason there is more than one navigation controller)
Is there a straightforward way to do this in SwiftUI?