What is the best way to change app tint color in a SwiftUI app?
It is powered by the new SwiftUI lifecycle so I do not have the option to perform self.?tintColor
Tried searching here but didn't find any way to do it in a SwiftUI lifecycle app.
What is the best way to change app tint color in a SwiftUI app?
It is powered by the new SwiftUI lifecycle so I do not have the option to perform self.?tintColor
Tried searching here but didn't find any way to do it in a SwiftUI lifecycle app.
This works without an EnvironmentKey
, and propagates to all views in the app:
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.accentColor(.red) // pick your own color
}
}
}
In the SceneDelegate.swift
where you create the window for your app you can set the tint color globally using the tintColor
property of UIWindow
let contentView = ContentView()
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
self.window?.tintColor = UIColor.red // Or any other color you want
window.makeKeyAndVisible()
}
Edit
After seeing that you want it for the new SwiftUI, you can create new EnvironmentKeys:
private struct TintKey: EnvironmentKey {
static let defaultValue: Color = Color.blue
}
extension EnvironmentValues {
var tintColor: Color {
get { self[TintKey.self] }
set { self[TintKey.self] = newValue }
}
}
@main
struct YourApp: App {
var body: some Scene {
WindowGroup {
ContentView().environment(\.tintColor, Color.red)
}
}
}
Then in your views you would use it like this:
struct ContentView: View {
@Environment(\.tintColor) var tintColor
var body: some View {
VStack {
Text("Hello, world!")
.padding()
Button(action: {}, label: {
Text("Button")
})
}.accentColor(tintColor)
}
}
Ariel, In this implementation, you can choose and use 'accentColor' throughout the entire application lifecycle. However, if you want to keep a value permanently, you should think about a solution, I hope you are a smart guy ...
enum MyColor: Identifiable, CaseIterable {
var id: String { UUID().uuidString }
case blue, green, orange, pink, purple, red, yellow
var currentColor: Color {
switch self {
case .blue:
return .blue
case .green:
return .green
case .orange:
return .orange
case .pink:
return .pink
case .purple:
return .purple
case .red:
return .red
case .yellow:
return .yellow
}
}
}
final class ViewModel: ObservableObject {
@Published
var isPresented = false
@Published
var myColor: MyColor = .blue
}
struct AppSettings: View {
@ObservedObject
var vm: ViewModel
var body: some View {
NavigationView {
Form {
Picker("Current color", selection: $vm.myColor) {
ForEach(MyColor.allCases) { color in
Label(
title: {
Text(color.currentColor.description.capitalized)
}, icon: {
Image(systemName: "circle.fill")
})
.tag(color)
.foregroundColor(color.currentColor)
}
}
}
.navigationBarItems(
trailing:
Button(
action: {
vm.isPresented.toggle()},
label: {
Text("Close")
}))
.navigationTitle("App settings")
}
}
}
struct ContentView: View {
@StateObject
private var vm = ViewModel()
var body: some View {
VStack {
Button(
action: {
vm.isPresented.toggle()
}, label: {
VStack {
Rectangle()
.fill(Color.accentColor)
.frame(width: 100, height: 100)
Text("Settings")
.font(.title)
}
})
}
.accentColor(vm.myColor.currentColor)
.sheet(
isPresented: $vm.isPresented) {
AppSettings(vm: vm)
.accentColor(vm.myColor.currentColor)
}
}
}