SwiftUI - TextField - 焦点上清除 Double 类型的值,取消选择时恢复

问题描述 投票:0回答:3

场景:

SwiftUI
中,我的
TextField
有一个
Double
值。点击/聚焦
TextField
时,当前
Double
值将被清除,以便用户可以轻松输入新值,而无需选择和删除当前值。如果用户没有输入新值,则取消选择时将恢复旧值。

问题

利用

.focused()
.onChange(of:)
这似乎是不可能的。下面的代码正确地清除了该值(在控制台中可见)。但是,更改并未反映在 UI 中。通过使用
.id()
上的
TextField
强制更新 UI 会取消选择
TextField
,从而使此解决方法毫无用处。

为什么 UI 没有因对

TextField
value 属性的更改而更新?

struct ContentView: View {
    
    @FocusState var focus: Bool
    @State var test: Double? = 100
    @State var id: UUID = UUID()
    
    var body: some View {
        VStack {
            TextField("Placeholder", value: $test, format: .number)
                .id(id)
                .focused($focus)
                .onChange(of: focus, perform: { editing in
                    var oldValue: Double? = test
                    if editing {
                        self.$test.wrappedValue = nil
                        self.$id.wrappedValue = UUID()
                    } else {
                        if test == nil {
                            self.$test.wrappedValue = oldValue
                            self.$id.wrappedValue = UUID()
                        }
                    }
                })
        }
        .padding()
    }
}

有没有办法用

SwiftUI
TextField
做到这一点?

ios swift swiftui textfield
3个回答
3
投票

Why UI not update from the change to the TextField value ?

因为它不会直接将 TextField 的值(String)绑定到您的值(Double)。

对于

clear value on focus, restore on deselect
,您需要在 TextField 上使用文本而不是值进行操作。这是一个例子:

struct TestView: View {
    @FocusState var focus: Bool
    @State var value: String = "100"
    @State private var oldValue: String = ""
    
    var body: some View {
        VStack {
            TextField("", text: .constant("other"))
            TextField("Placeholder", text: $value)
                .focused($focus)
                .onChange(of: focus) { editing in
                    if editing {
                        if !value.isEmpty {
                            oldValue = value
                            value = ""
                        }
                    } else {
                        if value.isEmpty {
                            value = oldValue
                        }
                    }
                }
        }
        .textFieldStyle(.roundedBorder)
        .padding()
    }
}

如果你只想让它成为 Double ,请在外部处理它(在 ViewModel 或其他东西中)


1
投票

扩展@meomeomeo'答案,请在下面找到一个可重用的

TextField
视图,满足
TextField
文本类型为
Double
的需要。

第二个

.onChange(of:)
在用户键入时更新输入绑定,但前提是键入的文本属于
Double
类型。这是为了防止用户在之前从未取消选择
TextField
。节省。

struct TextFieldDoubleClearView: View {
    
    @FocusState var focus: Bool
    
    @Binding var input: Double
    
    @State var value: String = "100"
    @State private var oldValue: String = ""
    
    var body: some View {
        VStack {
            TextField("Placeholder", text: $value)
                .keyboardType(.decimalPad)
                .focused($focus)
                .onChange(of: focus, perform: { editing in
                    if editing {
                        if !value.isEmpty {
                            oldValue = value
                            value = ""
                        }
                    } else {
                        if value.isEmpty {
                            value = oldValue
                        } else {
                            if let valueDouble: Double = Double(value) {
                                input = valueDouble
                            } else {
                                value = oldValue
                            }
                        }
                    }
                })
                .onChange(of: value, perform: { _ in
                    if let valueDouble: Double = Double(value) {
                        input = valueDouble
                    }
                })
        }
        .padding()
        .onAppear {
            value = String(input)
        }
    }
}   

0
投票

用户开始输入后是否可以以某种方式清除文本?我的意思是 TextField 变得聚焦,但用户没有开始输入 - 一旦他开始输入,就显示以前的文本 - 旧文本开始替换为新输入 @meomemeo ??

© www.soinside.com 2019 - 2024. All rights reserved.