Как изменить tintColor всего приложения? SwiftUI - PullRequest
2 голосов
/ 24 февраля 2020

Итак, я поддерживаю три темы в своем приложении, каждая с разными оттенками цвета. Я использую @EnvironmetObject для отслеживания изменений. Однако я не могу использовать его в файле SceneDelegate.swift, потому что приложение вылетает. Кроме того, accentColor не является опцией, так как он не меняет предупреждение tintColor. Как я могу это сделать?

Вот код:

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
    }
}

При таком подходе sh произойдет, когда приложение запускается, потому что оно не может найти объект @EnvironmentObject в своем предке.

файл ContentView.swift

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

Этот подход не будет работать и для меня потому что это не меняет цвет tintColor оповещений, например.

Изображения

This is what I get if I use accentColor

Это что я получу, если использую accentColor


This is what I want to achieve

Это то, чего я хочу достичь

1 Ответ

0 голосов
/ 24 февраля 2020

Обновление: опубликовал эту демонстрацию на GitHub - DemoWindowTint

Приведенная ниже демонстрация создается при настройке окна tintColor (который наследуется всеми подпредставлениями) с использованием подход, представленный в Как получить доступ к собственному окну в представлении SwiftUI? .

В демоверсии я использовал NavigationView с парой NavigationLinks и Button, показывая Alert.

demo

Проверено со следующими

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