0

下面我有我的选择器的代码:

struct pickerSwitch: View {
  @ObservedObject var appState: AppState
  @State var selection: String = "Red"
  var colors = ["Red", "Blue"]

  init(appState: AppState) {
        print("Init ran again")
        self.appState = appState
        if appState.showBlueControl {
            UISegmentedControl.appearance().setTitleTextAttributes([.font : UIFont.preferredFont(forTextStyle: .headline)], for: .normal)
            UISegmentedControl.appearance().backgroundColor = .blue
        } else {
            UISegmentedControl.appearance().setTitleTextAttributes([.font : UIFont.preferredFont(forTextStyle: .headline)], for: .normal)
            UISegmentedControl.appearance().backgroundColor = .red
        }
    }

  var body: some View {
        Picker(selection: $selection, label: Text("")) {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }.pickerStyle(SegmentedPickerStyle())
  }
}

在我的代码的其他地方,我有一个按钮可以更改“AppState”特定实例的“showBlueControl”值。在我的 Xcode 日志中,我看到很多“再次运行初始化”日志,所以我认为分段控件应该发生变化,但由于某种原因,只有在我完全关闭视图并重新打开它时才会发生变化。当 SwiftUI 状态发生变化(不关闭/重新打开视图)时,如何动态更改 SegmentedControl?

4

2 回答 2

0

您只需要@State跟踪背景颜色。然后你.background()在选择器上设置。要更改您的状态变量,只需使用.onChange.

struct PickerSwitch: View {
    @State var selection: String = "Red"
    var colors = ["Red", "Blue"]
    @State var backgroundColor = Color.red // This tracks your background color
    
    var body: some View {
        Picker(selection: $selection, label: Text("")) {
            ForEach(colors, id: \.self) {
                Text($0)
            }
        }
// .onChange reacts to the change of selection
        .onChange(of: selection, perform: { value in 
            if value == "Red" {
                backgroundColor = .red
            } else {
                backgroundColor = .blue
            }
        })
        .pickerStyle(SegmentedPickerStyle())
        .background(backgroundColor) // Set your background color here
    }
}
于 2021-07-29T15:31:07.923 回答
0

您可以使用SwiftUI-Introspect。我更喜欢这个而不是改变.id(_:)视图,因为:

当您更改视图的 ID 时,会导致它失效,然后重新创建。它还可能导致一些奇怪的错误,例如动画奇怪地停止,并且无法在中途更改选项卡以中断动画。但是,使用 Introspect,视图不会重新初始化。视图主体只是在更改时更新appState

此外,使用 Introspect 时,样式只会影响这个样式,而Picker不是整个应用程序中的每个样式。

我还简化了您处理跟踪颜色的方式。请注意,我们使用 绑定到所选颜色$appState.switchColor

代码:

struct ContentView: View {
    @StateObject private var appState = AppState()

    var body: some View {
        PickerSwitch(appState: appState)
    }
}
enum SwitchColor: String, CaseIterable, Identifiable {
    case red = "Red"
    case blue = "Blue"

    var id: String { rawValue }

    var color: UIColor {
        switch self {
        case .red: return .red
        case .blue: return .blue
        }
    }
}

class AppState: ObservableObject {
    @Published var switchColor: SwitchColor = .red
}
struct PickerSwitch: View {
    @ObservedObject var appState: AppState

    var body: some View {
        Picker("Select color", selection: $appState.switchColor) {
            ForEach(SwitchColor.allCases) { color in
                Text(color.rawValue).tag(color)
            }
        }
        .pickerStyle(.segmented)
        .introspectSegmentedControl { segmentedControl in
            let attributes = [NSAttributedString.Key.font : UIFont.preferredFont(forTextStyle: .headline)]
            segmentedControl.setTitleTextAttributes(attributes, for: .normal)
            segmentedControl.backgroundColor = appState.switchColor.color
        }
    }
}
于 2021-07-29T16:43:37.253 回答