我有两个选择器,一个用于优先级,另一个用于选择日期。我想根据优先级选择器的选择更改两个选择器的背景,例如,如果优先级高,选择器应该是红色,中间橙色等等...... 目前我只能使用初始化程序手动设置选择器的背景颜色。 这是我的视图代码:
struct AddWunschSheetView: View {
@State private var titelTextField: String = ""
@State private var kostenTextField: String = ""
@State private var sliderValue = 1.0
@State private var amount = 0.5
@State private var prioPicker = 1
@State private var selection = 1
@Environment(\.dismiss) var dismiss
init() {
UISegmentedControl.appearance().selectedSegmentTintColor = UIColor.red
let attributes: [NSAttributedString.Key:Any] = [
.foregroundColor: UIColor.white
]
UISegmentedControl.appearance().setTitleTextAttributes(attributes, for: .selected)
}
var body: some View {
NavigationStack {
Form {
Section("Artikeldetails") {
TextField("", text: $titelTextField, prompt: Text("Titel des Artikels"))
}
Section("Priority") {
Picker("", selection: $prioPicker) {
Text("Dringend").tag(1)
Text("Hoch").tag(2)
Text("Mittel").tag(3)
Text("Niedrig").tag(4)
}
.pickerStyle(.segmented)
}
Picker("", selection: $selection) {
Text("Tag").tag(1)
Text("Woche").tag(2)
Text("Monat").tag(3)
}
.pickerStyle(.segmented)
if selection == 1 {
Slider(value: $sliderValue, in: 1...31, step: 1.0, minimumValueLabel: Text("1"), maximumValueLabel: Text("31"), label: {})
.padding(.horizontal)
} else if selection == 2 {
Slider(value: $sliderValue, in: 1...52, step: 1.0, minimumValueLabel: Text("1"), maximumValueLabel: Text("52"), label: {})
.padding(.horizontal)
} else if selection == 3 {
Slider(value: $sliderValue, in: 1...12, step: 1.0, minimumValueLabel: Text("1"), maximumValueLabel: Text("12"), label: {})
.padding(.horizontal)
}
HStack {
Spacer()
Text( String(format: "%.0f", sliderValue))
if selection == 1 {
Text("Tage bis zum Ereigniss")
} else if selection == 2 {
Text("Wochen bis zum Ereigniss")
} else if selection == 3 {
Text("Monate bis zum Ereigniss")
}
Spacer()
}
HStack {
VStack {
Text("Kosten")
.bold()
TextField("", text: $kostenTextField, prompt: Text("0€"))
.keyboardType(.numberPad)
.padding(.top)
}
Spacer()
if prioPicker == 1 {
Gauge(value: amount) {
Text("50%")
}
.gaugeStyle(.accessoryCircularCapacity)
.tint(.red)
} else if prioPicker == 2 {
Gauge(value: amount) {
Text("50%")
}
.gaugeStyle(.accessoryCircularCapacity)
.tint(.orange)
} else if prioPicker == 3 {
Gauge(value: amount) {
Text("50%")
}
.gaugeStyle(.accessoryCircularCapacity)
.tint(.blue)
} else if prioPicker == 4 {
Gauge(value: amount) {
Text("50%")
}
.gaugeStyle(.accessoryCircularCapacity)
.tint(.green)
}
}
.padding(.horizontal)
}
.navigationTitle("Neuen Artikel hinzufügen")
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button("Save") {
dismiss()
}
}
}
}
}
}
用户界面如下所示:
我已经尝试过使用 if 语句自定义 init,我尝试过自定义部分、选择器...... 我什至不确定这是否可能。
正如您所发现的,向分段的
Picker
添加样式很困难。但是,您可以做的是使用与 iOS 中的分段选择器 - 处理已选定项目上的点击(这是我的答案)的答案中所示相同的技术:
.matchedGeometryEffect
.matchedGeometryEffect
的源。.matchedGeometryEffect
需要命名空间:
@Namespace private var ns
不再需要您之前使用旧版 UI 调用的
init
// init() {
// UISegmentedControl.appearance().selectedSegmentTintColor = UIColor.red
//
// let attributes: [NSAttributedString.Key:Any] = [
// .foregroundColor: UIColor.white
// ]
// UISegmentedControl.appearance().setTitleTextAttributes(attributes, for: .selected)
// }
我建议为您的优先级创建一个枚举,例如:
enum Priority: CaseIterable {
case dringend
case hoch
case mittel
case niedrig
var asString: String {
"\(self)".capitalized
}
var color: Color {
switch self {
case .dringend: .red
case .hoch: .orange
case .mittel: .blue
case .niedrig: .green
}
}
}
此枚举应用于保存优先级选择的状态变量:
@State private var prioPicker = Priority.dringend
然后可以按如下方式组装
Picker
:
Section("Priority") {
Picker("", selection: $prioPicker) {
ForEach(Priority.allCases, id: \.self) { priority in
Text(priority.asString)
}
}
.pickerStyle(.segmented)
.background {
// A row of placeholders
HStack(spacing: 0) {
ForEach(Priority.allCases, id: \.self) { priority in
Color.clear
.matchedGeometryEffect(id: priority, in: ns, isSource: true)
}
}
}
.overlay {
ZStack {
Rectangle()
.fill(prioPicker.color)
Text(prioPicker.asString)
.font(.footnote)
.fontWeight(.semibold)
.foregroundStyle(.white)
}
.matchedGeometryEffect(id: prioPicker, in: ns, isSource: false)
.clipShape(RoundedRectangle(cornerRadius: 7))
.animation(.easeOut(duration: 0.2), value: prioPicker)
}
}
Gauge
也可以简化为:
Gauge(value: amount) {
Text("50%")
}
.gaugeStyle(.accessoryCircularCapacity)
.tint(prioPicker.color)
它的外观如下:
有趣的是,
RoundedRectangle
夹子形状会自动采用方角作为内边缘,就像您希望的那样!