SwiftUI: собственный ViewModifier не обновляет представление

В моем проекте у меня есть два палитры цветов, которые меняют цвет фона и цвет шрифта.

Лист, на котором я меняю Цвет:

@ObservedObject var listColor: ListColor

ColorPicker("Hintergrund", selection: $listColor.bgColor)
                               
ColorPicker("Text", selection: $listColor.textColor)

ContentView, где должно отображаться изменение:

 @ObservedObject private var listColor = ListColor()
 
 VStack{
     VStack{...}
     .backgroundColor(listColor.bgColor)
     .foregroundColor(listColor.textColor)
 }
 .navigationBarTitle(Text("Workout"), displayMode: .automatic)
 .navigationBarColor(backgroundColor: listColor.bgColorNav, titleColor: listColor.textColorNav) // my own viewmodifier
  .navigationBarItems(trailing:
       Button(action: {
             self.showSettings.toggle()
       }) {
             Text("Settings")
                    
       }
       .sheet(isPresented: $showSettings){
            SettingsView(listColor: listColor) //open View with the color pickers
       })

                                    

У меня также есть собственный ViewModifer, который меняет цвет фона и цвет шрифта панели навигации.

struct NavigationBarModifier: ViewModifier {

var backgroundColor: UIColor?
var titleColor: UIColor?

init(backgroundColor: UIColor?, titleColor: UIColor?) {
    self.backgroundColor = backgroundColor
    let coloredAppearance = UINavigationBarAppearance()
    coloredAppearance.configureWithTransparentBackground()
    coloredAppearance.backgroundColor = backgroundColor
    coloredAppearance.titleTextAttributes = [.foregroundColor: titleColor ?? .white]
    coloredAppearance.largeTitleTextAttributes = [.foregroundColor: titleColor ?? .white]

    UINavigationBar.appearance().standardAppearance = coloredAppearance
    UINavigationBar.appearance().compactAppearance = coloredAppearance
    UINavigationBar.appearance().scrollEdgeAppearance = coloredAppearance
}

func body(content: Content) -> some View {
    ZStack{
        content
        VStack {
            GeometryReader { geometry in
                Color(self.backgroundColor ?? .clear)
                    .frame(height: geometry.safeAreaInsets.top)
                    .edgesIgnoringSafeArea(.top)
                Spacer()
            }
        }
    }
}
}

Проблема в том, что обычный фон и цвет шрифта меняются, но не на панели навигации. Я думаю, проблема в том, что мой собственный ViewModifier для панели навигации не перезагружает представление. Я сохраняю цвета в UserDefaults; когда я снова запускаю приложение, изменения отображаются на панели навигации.


person Lukas    schedule 08.11.2020    source источник


Ответы (1)


Вместо использования обычной переменной внутри ViewModifier объявите привязку к объекту Color. Затем, если ваше обернутое значение изменится, View (который в данном случае NavigationBar) будет автоматически перерисован.

Мой рабочий пример:

import SwiftUI

struct NavigationBarModifier: ViewModifier {
    var backgroundColor: Binding<Color>

    init(backgroundColor: Binding<Color>) {
        self.backgroundColor = backgroundColor
    }

    func body(content: Content) -> some View {
        ZStack{
            content
            VStack {
                GeometryReader { geometry in
                    self.backgroundColor.wrappedValue
                        .frame(height: geometry.safeAreaInsets.top)
                        .edgesIgnoringSafeArea(.top)
                    Spacer()
                }
            }
        }
    }
}

extension View {
    func navigationBarColor(_ bgColor: Binding<Color>) -> some View {
        self.modifier(NavigationBarModifier(backgroundColor: bgColor))
    }
}

struct ContentView: View {
    @State private var bgColor = Color(.sRGB, red: 0.98, green: 0.9, blue: 0.2)
    
    var body: some View {
        NavigationView {
            ColorPicker("NavigationBar background color", selection: $bgColor)
                .navigationBarTitle("Title", displayMode: .large)
                .navigationBarColor(self.$bgColor)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
person Nikolai    schedule 08.11.2020