TextField SwiftUI关闭键盘

t0ybt7op  于 2023-05-27  发布在  Swift
关注(0)|答案(6)|浏览(170)

如何在用户使用SwiftUI在TextField外部单击后关闭键盘?
我使用SwiftUI创建了一个TextField,但是我找不到任何解决方案,如果用户在TextField之外单击,则可以取消键盘。我看了一下TextFieldSwiftUI TextField documentation的所有属性,我找不到任何与关闭键盘相关的东西。
这是我的视图代码:

struct InputView: View {
    @State var inputValue : String = ""
    var body: some View {

        VStack(spacing: 10) {
            TextField("$", text: $inputValue)
                .keyboardType(.decimalPad)
        }
    }
}
1l5u6lss

1l5u6lss1#

这可以通过视图修改器来完成。

代码

public extension View {
    func dismissKeyboardOnTap() -> some View {
        modifier(DismissKeyboardOnTap())
    }
}

public struct DismissKeyboardOnTap: ViewModifier {
    public func body(content: Content) -> some View {
        #if os(macOS)
        return content
        #else
        return content.gesture(tapGesture)
        #endif
    }

    private var tapGesture: some Gesture {
        TapGesture().onEnded(endEditing)
    }

    private func endEditing() {
        UIApplication.shared.connectedScenes
            .filter {$0.activationState == .foregroundActive}
            .map {$0 as? UIWindowScene}
            .compactMap({$0})
            .first?.windows
            .filter {$0.isKeyWindow}
            .first?.endEditing(true)
    }
}

用法

backgroundView()
   .dismissKeyboardOnTap()

在这里查看演示:https://github.com/youjinp/SwiftUIKit

aydmsdu9

aydmsdu92#

这是使用DragGesture的解决方案,它正在工作。

struct ContentView: View {
    @State var text: String = ""
    var body: some View {
        VStack {
            TextField("My Text", text: $text)
                .keyboardType(.decimalPad)
        }
        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
        .edgesIgnoringSafeArea(.all)
        .gesture(
            TapGesture()
                .onEnded { _ in
                    UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
            }
        )
    }
}
8gsdolmq

8gsdolmq3#

将点击手势添加到最外部视图中,并在点击手势闭包中调用扩展方法。

struct InputView: View {
    @State var inputValue : String = ""
    var body: some View {
        
        VStack(spacing: 10) {
            TextField("$", text: $inputValue)
                .keyboardType(.decimalPad)
        } .onTapGesture(perform: {
            self.endTextEditing()
        })
    }
}

extension View {
    func endTextEditing() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder),
                                        to: nil, from: nil, for: nil)
    }
}
9njqaruj

9njqaruj4#

TextField("Phone Number", text: $no)
    .keyboardType(.numbersAndPunctuation)
    .padding()
    .background(Color("4"))
    .clipShape(RoundedRectangle(cornerRadius: 10))
    .offset(y:-self.value).animation(.spring()).onAppear() {
         NotificationCenter.default.addObserver(forName:UIResponder.keyboardWillShowNotification, object: nil, queue: .main){ (notif)in
        let value  = notif.userInfo![UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
            let height = value.height
            self.value = height

        }
        NotificationCenter.default.addObserver(forName:UIResponder.keyboardWillHideNotification, object: nil, queue: .main){ (notification)in
        self.value = 0
    }
}
9nvpjoqh

9nvpjoqh5#

在SwiftUI 3中,@FocusState Package 器可用于从可编辑字段中移除或切换焦点。当焦点从字段中移除时,键盘关闭。所以在你的例子中,这只是一个给TextView周围空间空间和手势的问题。

struct ContentView: View {
    @State var inputValue : String = ""
    @FocusState private var inputIsFocused: Bool
    var body: some View {
        VStack(spacing: 10) {
            TextField("$", text: $inputValue)
                .keyboardType(.decimalPad)
                .border(Color.green)
                .focused($inputIsFocused)
            
        }
        .frame(maxHeight: .infinity) // If input is supposed to be in the center
        .background(.yellow)
        .onTapGesture {
            inputIsFocused = false
        }
    }
}

但是我们可以用@FocusState做更有趣的事情。在表单中从一个字段切换到另一个字段怎么样?如果你点击离开,键盘也解散。

struct ContentView: View {
    enum Field {
        case firstName
        case lastName
        case emailAddress
    }

    @State private var firstName = ""
    @State private var lastName = ""
    @State private var emailAddress = ""
    @FocusState private var focusedField: Field?

    var body: some View {
        ZStack {
            VStack {
                TextField("Enter first name", text: $firstName)
                    .focused($focusedField, equals: .firstName)
                    .textContentType(.givenName)
                    .submitLabel(.next)
                
                TextField("Enter last name", text: $lastName)
                    .focused($focusedField, equals: .lastName)
                    .textContentType(.familyName)
                    .submitLabel(.next)
                
                TextField("Enter email address", text: $emailAddress)
                    .focused($focusedField, equals: .emailAddress)
                    .textContentType(.emailAddress)
                    .submitLabel(.join)
            }
            .onSubmit {
                switch focusedField {
                case .firstName:
                    focusedField = .lastName
                case .lastName:
                    focusedField = .emailAddress
                default:
                    print("Creating account…")
                }
            }
        }
        .textFieldStyle(.roundedBorder)
        .padding()
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .contentShape(Rectangle()) // So ZStack becomes clickable
        .onTapGesture {
            focusedField = nil
        }
    }
}
hsvhsicv

hsvhsicv6#

我想这可能是最简单的方法

extension View {
    func hideKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}

struct test: View {
    @State private var pass = ""

    var body: some View {
        ZStack {
            Color.white.edgesIgnoringSafeArea(.all)
                .onTapGesture(perform: {
                    self.hideKeyboard()
                })

            VStack {
                TextField("测试", text: $pass)
                    .font(.largeTitle)
                    .foregroundColor(.red)
                    .frame(width: 350, height: 90)
                    .textFieldStyle(.roundedBorder)
                    .buttonBorderShape(.roundedRectangle)
                    .multilineTextAlignment(.center)
            }
        }
    }
}

相关问题