TL;DR To make sure all child views inherit the tint/accent color, including those on modal windows, set the TintColor on the root window in SceneDelegate:
//In SceneDelegate.swift
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
//set the tintColor to be applied globally
self.window?.tintColor = UIColor.red
window.makeKeyAndVisible()
}
About
In SwiftUI, tint colors are called accent colors, and you can set them on individual views and controls like this:
Button("Hello", action: {}).accentColor(.green)
As with tintColor, accentColor is inherited by child views from their parent. and to set them globally for the entire app, we go to SceneDelegate and set apply an .accentColor()
property to our root view.
Problem with global accentColor
To apply an accentColor globally so that it is inherited by all views, one recommendation I’ve come across is to set the accentColor property on the root SwiftUI view inside SceneDelagate, as shown here.
//In SceneDelegate.swift
let contentView = ContentView().accentColor(.red)
The problem I came across when doing this way is that any view opened as a modal sheet will not inherit the accent color, as we can see below.
In this example, the same view with the Button is loaded both by a regular NavigationLink as well as modally through .sheet(). When opened modally, the Button does not inherit the red color, instead it remains the default blue.
Use tintColor Instead
The solution I came across is instead of applying .accentColor to the root SwiftUI view (contentView in our example), we can use the regular old .tintColor property on the root view controller like this:
//In SceneDelegate.swift
let contentView = ContentView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
//Set our tintColor her to the root window controller
self.window?.tintColor = UIColor.red
window.makeKeyAndVisible()
Now, when we open the new window modally, we will see the Button showing our new red tint color
Below is a full example of the code I used for testing. Note how the same View SubView
is being loaded either through NavigationLink or as a sheet.
//ContentView.swift
//Note: Set the .tintColor in SceneDelegate using the example above to change the accent / tint colors
import SwiftUI
struct ContentView: View {
@State var showSheet = false
var body: some View {
NavigationView {
VStack {
NavigationLink("Navigation Link", destination: SubView())
.padding()
Button("Open Modal", action: {
self.showSheet.toggle()
})
}
.navigationBarItems(
leading: Button("Nav Item",
action: {}))
.sheet(isPresented: self.$showSheet, content: {
SubView()
})
}
}
}
struct SubView: View {
var body: some View {
VStack {
Text("This window should inherit the tint/accent color")
.padding()
Button("Button", action:{})
}
}
}
You must be logged in to post a comment.