我在使用 TextField 输入货币金额时遇到了 SwiftUI 最终用户的可用性问题。
绑定字段为双精度型,初始设置为0,显示文本字段时提示为$0.00。
问题是,当用户想要输入一个值时,他们必须手动使用退格键删除 0.00。另外,如果他们不小心在 $ 符号上退格,则此后输入的任何值都会消失!
当存在多个货币字段时,这对最终用户来说是一个真正的麻烦。
我在互联网上看到了在 NumberFormatter 中设置
formatter.zeroSymbol = ""
的建议,但是当 numberStyle = .currency
时,输入的任何值都会丢失/损坏。
如果我将数字样式更改为
.decimal
,我可以使用 zeroSymbol
选项,它似乎可以工作,但我会丢失货币格式。
有谁知道如何解决这个问题吗?
以下是您可以运行的示例代码来演示此问题。
import SwiftUI
struct ContentView: View {
@State private var amount: Double = 0
let currencyFormat: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
// formatter.zeroSymbol = ""
return formatter
}()
var body: some View {
HStack {
Text("Enter Amount")
Spacer()
TextField("", value: $amount, formatter: currencyFormat)
.keyboardType(.numbersAndPunctuation)
}
.padding()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
详细阐述@Zulqarnain Naveed 的答案:
TextField("",value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
添加以下代码行。当聚焦时,这将选择文本字段中的所有文本:
.onReceive(NotificationCenter.default.publisher(for: UITextField.textDidBeginEditingNotification)) { obj in
if let textField = obj.object as? UITextField {
textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument)
}
}
代替这个:
TextField("", value: $amount, formatter: currencyFormat)
.keyboardType(.numbersAndPunctuation)
使用这个:
TextField("",value: $amount, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
这是对我有用的解决方法。它使用 FocusState 在两个格式化程序之间切换。
import SwiftUI
struct ContentView: View {
@State private var amount: Double = 0
var body: some View {
HStack {
Text("Enter Amount")
Spacer()
CurrencyTextField(title: "", value: $amount)
}
.padding()
}
}
struct CurrencyTextField: View {
var title: String
@Binding var value: Double
@FocusState private var isFocused: Bool
private let currencyNumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
return formatter
}()
private let decimalNumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.usesGroupingSeparator = false
return formatter
}()
var body: some View {
TextField(title, value: $value, formatter: isFocused ? decimalNumberFormatter : currencyNumberFormatter)
.keyboardType(.decimalPad)
.focused($isFocused)
}
}
#Preview {
ContentView()
}