📘

[SwiftUI]TextFieldで編集状態を変更する

2021/06/21に公開

iOSのSwiftUIでTextFieldの編集状態によって、Viewの出しわけをしたい時があります。
例えば、編集中は下部のボタンを非表示にしたい場合などです。

TextFieldで編集状態を検知する

SwiftUIのTextFieldの定義は以下のようになっています。

init<S>(_ title: S, text: Binding<String>, onEditingChanged: @escaping (Bool) -> Void = { _ in }, onCommit: @escaping () -> Void = {}) where S : StringProtocol

編集状態の検知はonEditingChangedで行います。

struct ContentView: View {
    
    @State var text: String = ""
    @State var editing: Bool = false
    
    var body: some View {
        
        VStack(spacing: 16.0) {
            TextField.init("enter text", text: self.$text, onEditingChanged: { editingChanged in
                debugPrint("onEditingChanged:\(editingChanged)")
                self.editing = editingChanged
            })
            if self.editing {
                Text("editing")
            }
            Spacer()
        }.padding()
        .contentShape(RoundedRectangle(cornerRadius: 0.0))
        .onTapGesture {
            debugPrint("onTap")
            UIApplication.shared.endEditing()
        }
        
    }
}

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

onEditingChangedで受け取った値を@State var editing: Boolに渡して、テキストの出しわけをしています。

TextFieldのフォーカスを外す方法

現在、標準でフォーカスを外す方法はiOSには備わっておりません。(watchOS/tvOSにはあります)
フォーカスを外すには以下のようにUIKitを使用します。


struct Content: View {

.....

        .contentShape(RoundedRectangle(cornerRadius: 0.0))
        .onTapGesture {
            debugPrint("onTap")
            UIApplication.shared.endEditing()
        }

.....

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

小技ですが、contentShapeを使うことで、タップエリアを広げています。

参考

Discussion