How to change tintColor of whole app? SwiftUI

自闭症网瘾萝莉.ら 提交于 2020-03-20 05:58:32

问题


So, I am supporting three themes in my app, each with different tintColors. I'm using @EnvironmetObject to track changes. However, I can't use it on SceneDelegate.swift file, because the app crashes. Moreover, accentColor is not an option, as it doesn't change alert tintColor. How can I do it?

Here's some code:

SceneDelegate.swift file

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

@EnvironmentObject var userData: UserData

var window: UIWindow?

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).

    // Create the SwiftUI view that provides the window contents.
    let contentView = TasksView()

    // Use a UIHostingController as window root view controller.
    if let windowScene = scene as? UIWindowScene {
        let window = UIWindow(windowScene: windowScene)
        window.rootViewController = UIHostingController(rootView: contentView.environmentObject(UserData()))
        self.window = window
        window.makeKeyAndVisible()

        window.tintColor = userData.selectedTheme.tintColor
    }
}

This approach will crash when the app starts, because it can't finde an @EnvironmentObject in its ancestor.

ContentView.swift file

struct ContentView: View {

    @EnvironmentObject var userData: UserData

    var body: some View {
        NavigationView{
            List(userData.tasks) { task in
                TaskRow(taskTitle: task.title, taskDetail: task.detail)
            }
            .navigationBarTitle(Text("Tasks"), displayMode: .automatic)

            .navigationBarItems(
                leading: NavigationLink(destination: SettingsView(), label: {
                    Image(systemName: "gear").imageScale(.large)
                }),
                trailing: NavigationLink(destination: AddTaskView(), label: {
                    Image(systemName: "plus").imageScale(.large)
                })
            )
        }.navigationViewStyle(StackNavigationViewStyle())
         .accentColor(userData.selectedTheme.accentColor)
    }
}

This approach won't work for me either because it doesn't change the tintColor of alerts, for example.

Images

This is what I get if I use accentColor


This is what I want to achieve


回答1:


Update: posted this demo on GitHub - DemoWindowTint

The below demo is created on setting window's tintColor (which is inherited by all subviews) using the approach provided in How to access own window within SwiftUI view?.

In demo I used NavigationView with couple of NavigationLinks and Button showing Alert.

Tested with following

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?


    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

        if let windowScene = scene as? UIWindowScene {
            let window = UIWindow(windowScene: windowScene)

            let contentView = ContentView()
                .environment(\.hostingWindow, { [weak window] in
                    return window })

            window.rootViewController = UIHostingController(rootView: contentView)

            self.window = window
    ...

struct ContentView: View {
    @Environment(\.hostingWindow) var hostingWindow
   ... // body can be any

    .onAppear {
            // can be loaded from UserDefaults here, and later changed on any action
            self.hostingWindow()?.tintColor = UIColor.red
    }


来源:https://stackoverflow.com/questions/60368765/how-to-change-tintcolor-of-whole-app-swiftui

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!