SwiftUI 中 <Double> 类型输入的 TextField 清除按钮
TextField clean button for inputs of type <Double> in SwiftUI
你能帮我清除按钮代码吗,它不能正常工作?
我有一个 TextField,它存储一个 Double 类型的输入,不幸的是,包含附加修饰符的经典解决方案不起作用。
这是我的代码:
import SwiftUI
struct ContentView: View {
@State private var amount: Double = 10
@FocusState private var isFocused: Bool
var body: some View {
NavigationView {
Form {
Section {
TextField("Amount to pay", value: $amount, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
.focused($isFocused)
.modifier(TextFieldClearButton(amount: $amount, focus: $isFocused))
}
}
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isFocused = false
}
}
}
}
}
struct TextFieldClearButton: ViewModifier {
@Binding var amount: Double
@FocusState.Binding var focus: Bool
func body(content: Content) -> some View {
HStack {
content
if amount != 0.0 {
Button(
action: {
self.amount = 0.0
if focus == false {
focus = true
}
},
label: {
Image(systemName: "delete.left")
.foregroundColor(Color(UIColor.opaqueSeparator))
}
)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
当我调用修改器时,视图似乎没有更新,所以我只能看到默认值。我该如何解决这个问题?
我发现当 TextField
获得焦点时,您无法从外部更新该值。它只是忽略它。因此,为了让 Textfield
在聚焦时更新,您还必须引起视图刷新。最简单的方法是在 TextField
上放置一个 .id()
,其值可以像这样更改:
struct ButtonClearTextField: View {
// Your Double is now optional
@State private var amount: Double? = 10
@FocusState private var isFocused: Bool
@State var updater = UUID()
var body: some View {
Form {
Section {
TextField("Amount to pay", value: $amount, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
.focused($isFocused)
// Put the id in the view. I put it here as it helps indicate what is changing.
.id(updater)
// textFieldClearButton is a func on View as a result of the extension
.textFieldClearButton(amount: $amount, focus: $isFocused, updater: $updater)
// I added this button so you could test that if
// the TextField is focused it won't change.
Button {
amount = 0
} label: {
Text("Clear")
}
}
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isFocused = false
}
}
}
}
}
struct TextFieldClearButton: ViewModifier {
@Binding var amount: Double?
@FocusState.Binding var focus: Bool
@Binding var updater: UUID
func body(content: Content) -> some View {
HStack {
content
if amount != 0.0 {
Button(
action: {
// Setting to nil clears the field
amount = nil
// After setting the value,
updater = UUID()
DispatchQueue.main.async {
focus = true
}
},
label: {
Image(systemName: "delete.left")
.foregroundColor(Color(UIColor.opaqueSeparator))
}
)
}
}
}
}
// Creates func textFieldClearButton
extension View {
func textFieldClearButton(amount: Binding<Double?>, focus: FocusState<Bool>.Binding, updater: Binding<UUID>) -> some View {
self.modifier(TextFieldClearButton(amount: amount, focus: focus, updater: updater))
}
}
为了获得 Asperi 链接到的行为,您只需使用一个可选值并将其设置为 nil。
我还做了一个 View
扩展来稍微清理一下调用站点的代码。
你能帮我清除按钮代码吗,它不能正常工作?
我有一个 TextField,它存储一个 Double 类型的输入,不幸的是,包含附加修饰符的经典解决方案不起作用。
这是我的代码:
import SwiftUI
struct ContentView: View {
@State private var amount: Double = 10
@FocusState private var isFocused: Bool
var body: some View {
NavigationView {
Form {
Section {
TextField("Amount to pay", value: $amount, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
.focused($isFocused)
.modifier(TextFieldClearButton(amount: $amount, focus: $isFocused))
}
}
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isFocused = false
}
}
}
}
}
struct TextFieldClearButton: ViewModifier {
@Binding var amount: Double
@FocusState.Binding var focus: Bool
func body(content: Content) -> some View {
HStack {
content
if amount != 0.0 {
Button(
action: {
self.amount = 0.0
if focus == false {
focus = true
}
},
label: {
Image(systemName: "delete.left")
.foregroundColor(Color(UIColor.opaqueSeparator))
}
)
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
当我调用修改器时,视图似乎没有更新,所以我只能看到默认值。我该如何解决这个问题?
我发现当 TextField
获得焦点时,您无法从外部更新该值。它只是忽略它。因此,为了让 Textfield
在聚焦时更新,您还必须引起视图刷新。最简单的方法是在 TextField
上放置一个 .id()
,其值可以像这样更改:
struct ButtonClearTextField: View {
// Your Double is now optional
@State private var amount: Double? = 10
@FocusState private var isFocused: Bool
@State var updater = UUID()
var body: some View {
Form {
Section {
TextField("Amount to pay", value: $amount, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
.focused($isFocused)
// Put the id in the view. I put it here as it helps indicate what is changing.
.id(updater)
// textFieldClearButton is a func on View as a result of the extension
.textFieldClearButton(amount: $amount, focus: $isFocused, updater: $updater)
// I added this button so you could test that if
// the TextField is focused it won't change.
Button {
amount = 0
} label: {
Text("Clear")
}
}
}
.toolbar {
ToolbarItemGroup(placement: .keyboard) {
Spacer()
Button("Done") {
isFocused = false
}
}
}
}
}
struct TextFieldClearButton: ViewModifier {
@Binding var amount: Double?
@FocusState.Binding var focus: Bool
@Binding var updater: UUID
func body(content: Content) -> some View {
HStack {
content
if amount != 0.0 {
Button(
action: {
// Setting to nil clears the field
amount = nil
// After setting the value,
updater = UUID()
DispatchQueue.main.async {
focus = true
}
},
label: {
Image(systemName: "delete.left")
.foregroundColor(Color(UIColor.opaqueSeparator))
}
)
}
}
}
}
// Creates func textFieldClearButton
extension View {
func textFieldClearButton(amount: Binding<Double?>, focus: FocusState<Bool>.Binding, updater: Binding<UUID>) -> some View {
self.modifier(TextFieldClearButton(amount: amount, focus: focus, updater: updater))
}
}
为了获得 Asperi 链接到的行为,您只需使用一个可选值并将其设置为 nil。
我还做了一个 View
扩展来稍微清理一下调用站点的代码。