问题描述
我希望能够在用户逐个字符键入时编辑文本字段。我希望能够在用户键入时输入数字字段:
如果用户输入无效字符,则返回不包含无效字符的字符串。 我被困在如何捕获 TextField、编辑它并按照我显示的格式返回它。
我已经走了这么远:(不远:-) 我已经在 StackOverflow 上尝试了许多解决方案,但似乎没有一个让我想去我想去的地方.. 在编辑更改 onChange 等
struct SwiftUIView:视图 {
@State var amount: String = "0.00"
var body: some View {
TextField(
"Enter amount here ",text: $amount
)
}
}
解决方法
我怀疑我的要求太宽泛了,可能有点想为我做编程。事实并非如此,但也许我可以将范围缩小一点。
无论如何,我能够达到我想要的结果。我认为这是一个巨大的 KLUDGE,但这是我所能想到的。
首先是我的 SwiftUI 视图:
struct SwiftUIView: View {
@State var someText: String = "0.00"
@State var oldText: String = ""
@State var amount: Double = 0.00
var body: some View {
VStack {
TextField("Enter some text here",text: $someText,onCommit: {
print("someText = \(someText)")
self.amount = Double(someText)!
}
)
.onChange(of: someText,perform: { value in
if someText != oldText {
someText = editInputNumber(textIn: someText)
oldText = someText
}
}
)
Text("The amount entered was \(self.amount)")
}
}
}
使用 onChange 我遇到了以编程方式更改绑定字段第二次触发 onChange 的问题。这是 Kludge 的最大部分,我必须在其中测试对 onChange 的第二次调用。
然后是我创建的用于响应用户输入的函数。 这个函数是从视图中调用的,它接受字符串并首先调用一个函数将其过滤为仅数字。消除任何意外输入的非数字
它接受结果并将其提交给格式化函数并取回格式化的字符串。
func editInputNumber(textIn: String) -> String
{
var fixedText = ""
var charactersWork = [Character]()
charactersWork = getNumericInputString(textIn: textIn)
fixedText = formatDecimalNumericString(charactersWork:
charactersWork)
return fixedText
}
将输入字符串过滤为仅数字的功能。它也过滤掉先前条目中的任何前导零。
func getNumericInputString(textIn: String) -> [Character]
{
var leadingZero = true
let charactersIn = Array(textIn)
var charactersOut = [Character]()
for i in 0..<charactersIn.count {
if charactersIn[i].isNumber {
if let number = Int(String(charactersIn[i]))
{
if number > 0
{
leadingZero = false
}
}
if !leadingZero {
charactersOut.append(charactersIn[i])
}
}
}
return charactersOut
}
在字符串被过滤成只有数字的字符数组后,此函数将其格式化以输出回视图。如果是输入的前两个数字,则函数格式在值的前导零。
func formatDecimalNumericString(charactersWork: [Character]) -
> String
{
let number: String = "000"
var charactersOut = [Character]()
if charactersWork.count < 3
{
charactersOut = Array(number)
}
if charactersWork.count > 0
{
if charactersWork.count == 1
{
charactersOut[2] = charactersWork[0]
}
if charactersWork.count == 2
{
charactersOut[1] = charactersWork[0]
charactersOut[2] = charactersWork[1]
}
if charactersWork.count > 2
{
for i in 0..<charactersWork.count
{
charactersOut.append(charactersWork[i])
}
}
charactersOut.insert(".",at: (charactersOut.count - 2))
}
return String(charactersOut)
}