我最近开始学习SwiftUI,我想做一个单位转换器。在这个过程中,我遇到了一个问题:必须确保当将一个数值输入其中一个TextField时,会触发其余的TextField公式,并显示总值。
import SwiftUI
import Combine
struct ContentView: View {
@State var celsius: String = ""
@State var kelvin: String = ""
@State var farenheit: String = ""
@State var reyumur: String = ""
@State var rankin: String = ""
var body: some View {
NavigationView {
Temperature(celsius: $celsius, kelvin: $kelvin, farenheit: $farenheit, reyumur: $reyumur, rankin: $rankin)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct Temperature: View {
@Binding var celsius: String
@Binding var kelvin: String
@Binding var farenheit: String
@Binding var reyumur: String
@Binding var rankin: String
var body: some View {
List {
Section(
header: Text("Международная система (СИ)")) {
HStack {
TextField("Enter value", text: $celsius)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(celsius)) { newValue in
let filtered = newValue.filter { "0123456789.".contains($0) }
if filtered != newValue {
self.celsius = filtered
}
}
Text("°C")
.padding(.horizontal)
.font(.headline)
.foregroundColor(.blue)
}
HStack {
TextField("Enter value", text: $kelvin)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(kelvin)) { newValue in
let filtered = newValue.filter { "0123456789.".contains($0) }
if filtered != newValue {
self.kelvin = filtered
}
}
Text("K")
.padding(.horizontal)
.font(.headline)
.foregroundColor(.blue)
}
}
Section(
header: Text("США и Британия")) {
HStack {
TextField("Enter value" , text: $farenheit)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(farenheit)) { newValue in
let filtered = newValue.filter { "0123456789.".contains($0) }
if filtered != newValue {
self.farenheit = filtered
}
}
Text("F")
.padding(.horizontal)
.font(.headline)
.foregroundColor(.blue)
}
}
Section(
header: Text("Редкоиспользуемые")) {
HStack {
TextField("Enter value" , text: $reyumur)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(reyumur)) { newValue in
let filtered = newValue.filter { "0123456789.".contains($0) }
if filtered != newValue {
self.reyumur = filtered
}
}
Text("Re")
.padding(.horizontal)
.font(.headline)
.foregroundColor(.blue)
}
HStack {
TextField("Enter value" , text: $rankin)
.keyboardType(.numbersAndPunctuation)
.onReceive(Just(rankin)) { newValue in
let filtered = newValue.filter { "0123456789.".contains($0) }
if filtered != newValue {
self.rankin = filtered
}
}
Text("R")
.padding(.horizontal)
.font(.headline)
.foregroundColor(.blue)
}
}
}
.navigationBarTitle("Temperature")
.navigationBarTitleDisplayMode(.inline)
}
}
发布于 2021-06-27 16:52:27
在SwiftUI 3中,@FocusState
可以用来检测TextField
是否被聚焦,这使得可以根据它的值执行不同的工作。您可以将一个变量设置为主变量,并从中计算其他值。对于每个值,使用两个函数进行正向和反向计算:
struct CelsiusAndKelvin: View {
@State private var celsius: String = "" // Assume all other values are based on celsius
@FocusState private var isKelvinFocused: Bool // When focused,
@State private var kelvinWhenFocused: String? // you may not want it to be calculated from other values
private var kelvinMask: Binding<String> {
Binding { // If `isKelvinFocused` turns true, this getter will be called first
if isKelvinFocused && kelvinWhenFocused != nil {
return kelvinWhenFocused!
}
if let x = Double(celsius) {
return String(format: "%.2f", c2k(x))
}
return ""
} set: {
if isKelvinFocused { kelvinWhenFocused = $0 }
if let x = Double($0) {
celsius = String(format: "%.2f", k2c(x))
} else {
celsius = ""
}
}
}
var body: some View {
Form {
TextField("°C", text: $celsius)
TextField("K", text: kelvinMask)
.focused($isKelvinFocused)
}
.onChange(of: isKelvinFocused) {
// Make `isKelvinFocused` always equal to `kelvinWhenFocused != nil`
if !$0 { kelvinWhenFocused = nil }
}
}
}
extension CelsiusAndKelvin {
private func c2k(_ x: Double) -> Double {
return x + 273.15
}
private func k2c(_ x: Double) -> Double {
return x - 273.15
}
}
https://stackoverflow.com/questions/68151960
复制相似问题