【问题标题】:UISegmentedControl not changing when state change occurs发生状态更改时 UISegmentedControl 不更改
【发布时间】:2021-07-29 14:02:58
【问题描述】:

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

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?

【问题讨论】:

  • 您在哪里更新分段更改时的 appState?
  • 您可以通过.id(selection).id(appState.showBlueControl) 重新创建您的视图
  • 附加 .id(selection) 无效,但使用 .id(appState.showBlueControl) 有效——谢谢!
  • 什么是 AppState?你真的需要Minimal, Reproducible Example
  • 请记住:通过使用它,您将再次创建一个整体视图。

标签: swift xcode swiftui segmentedcontrol


【解决方案1】:

您只需要一个@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
    }
}

【讨论】:

    【解决方案2】:

    您可以使用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
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-05-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      • 1970-01-01
      • 2015-05-16
      • 2020-05-08
      • 2020-01-28
      • 1970-01-01
      相关资源
      最近更新 更多